ScriptControllerIconView: Update to reflect policy type
This commit is contained in:
@@ -513,17 +513,20 @@ class BrowserViewController: UIViewController
|
|||||||
numBlockedScripts += 1
|
numBlockedScripts += 1
|
||||||
}
|
}
|
||||||
|
|
||||||
var scriptsAllowedForHost = false
|
var policy: ScriptPolicy? = nil
|
||||||
if let url = webView.url, let host = url.host, policyManager.allowedOriginsForScriptResources().contains(host) {
|
if let url = webView.url, let host = url.host {
|
||||||
scriptsAllowedForHost = true
|
policy = policyManager.scriptPolicy(forOrigin: host)
|
||||||
}
|
}
|
||||||
|
|
||||||
let iconView = toolbarController.scriptControllerIconView
|
let iconView = toolbarController.scriptControllerIconView
|
||||||
iconView.shieldsDown = tab.javaScriptEnabled
|
iconView.shieldsDown = tab.javaScriptEnabled
|
||||||
iconView.someScriptsAllowed = scriptsAllowedForHost
|
// iconView.setBlockedScriptsNumber(numBlockedScripts)
|
||||||
iconView.setBlockedScriptsNumber(numBlockedScripts)
|
|
||||||
|
|
||||||
// iconView.isEnabled = (webView.url != nil)
|
if let policy = policy {
|
||||||
|
iconView.currentPolicy = policy
|
||||||
|
}
|
||||||
|
|
||||||
|
iconView.isEnabled = (webView.url != nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
public func createNewTab(withURL url: URL?) {
|
public func createNewTab(withURL url: URL?) {
|
||||||
|
|||||||
@@ -125,11 +125,13 @@ class ReliefButton: UIButton
|
|||||||
|
|
||||||
override func imageRect(forContentRect contentRect: CGRect) -> CGRect {
|
override func imageRect(forContentRect contentRect: CGRect) -> CGRect {
|
||||||
let ratio = CGFloat(0.45)
|
let ratio = CGFloat(0.45)
|
||||||
|
let constantSize = round(ratio * contentRect.width)
|
||||||
return CGRect(
|
return CGRect(
|
||||||
origin: .zero,
|
origin: .zero,
|
||||||
size: CGSize(
|
size: CGSize(
|
||||||
width: ratio * contentRect.width,
|
// Ensure multiple of two for proper centering.
|
||||||
height: ratio * contentRect.width
|
width: constantSize + constantSize.truncatingRemainder(dividingBy: 2),
|
||||||
|
height: constantSize + constantSize.truncatingRemainder(dividingBy: 2)
|
||||||
)
|
)
|
||||||
).centered(inRect: contentRect)
|
).centered(inRect: contentRect)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,17 +13,16 @@ class ScriptControllerIconView: ReliefButton
|
|||||||
didSet { setNeedsLayout() }
|
didSet { setNeedsLayout() }
|
||||||
}
|
}
|
||||||
|
|
||||||
public var someScriptsAllowed: Bool = false {
|
@Invalidating(.layout)
|
||||||
didSet { setNeedsLayout() }
|
public var currentPolicy: ScriptPolicy = ScriptPolicy(securityOrigin: "", policyType: .alpha)
|
||||||
}
|
|
||||||
|
|
||||||
private let labelView = UILabel(frame: .zero)
|
private let labelView = UILabel(frame: .zero)
|
||||||
|
private let policyImageView = UIImageView(frame: .zero)
|
||||||
|
|
||||||
private let shieldsDownImage = UIImage(systemName: "shield.slash")
|
private let shieldsDownImage = UIImage(systemName: "shield.slash")
|
||||||
private let shieldsUpImage = UIImage(systemName: "shield")
|
private let shieldsUpImage = UIImage(systemName: "shield")
|
||||||
private let shieldsPartiallyUpImage = UIImage(systemName: "shield.lefthalf.fill")
|
private let shieldsPartiallyUpImage = UIImage(systemName: "shield.lefthalf.fill")
|
||||||
|
|
||||||
|
|
||||||
override init() {
|
override init() {
|
||||||
super.init()
|
super.init()
|
||||||
|
|
||||||
@@ -37,6 +36,8 @@ class ScriptControllerIconView: ReliefButton
|
|||||||
labelView.font = .boldSystemFont(ofSize: 8)
|
labelView.font = .boldSystemFont(ofSize: 8)
|
||||||
labelView.textColor = .white
|
labelView.textColor = .white
|
||||||
|
|
||||||
|
policyImageView.contentMode = .scaleAspectFit
|
||||||
|
|
||||||
setBlockedScriptsNumber(0)
|
setBlockedScriptsNumber(0)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -62,13 +63,34 @@ class ScriptControllerIconView: ReliefButton
|
|||||||
labelView.center = CGPoint(x: bounds.center.x + 10, y: bounds.center.y + 10)
|
labelView.center = CGPoint(x: bounds.center.x + 10, y: bounds.center.y + 10)
|
||||||
labelView.bounds = labelView.bounds.insetBy(dx: -3.0, dy: -2.0)
|
labelView.bounds = labelView.bounds.insetBy(dx: -3.0, dy: -2.0)
|
||||||
|
|
||||||
|
let policyImageWidth = round(bounds.width / 3)
|
||||||
|
let policyImageSize = CGSize(
|
||||||
|
// Make multiple of 2 to ensure proper centering
|
||||||
|
width: policyImageWidth - policyImageWidth.truncatingRemainder(dividingBy: 2),
|
||||||
|
height: policyImageWidth - policyImageWidth.truncatingRemainder(dividingBy: 2)
|
||||||
|
)
|
||||||
|
|
||||||
|
if let imageView = imageView {
|
||||||
|
imageView.addSubview(policyImageView)
|
||||||
|
policyImageView.frame = CGRect(origin: .zero, size: policyImageSize)
|
||||||
|
.centered(inRect: imageView.bounds)
|
||||||
|
.offsetBy(dx: 0.0, dy: -1.0)
|
||||||
|
}
|
||||||
|
|
||||||
if shieldsDown {
|
if shieldsDown {
|
||||||
setImage(shieldsDownImage, for: .normal)
|
setImage(shieldsDownImage, for: .normal)
|
||||||
} else {
|
|
||||||
if someScriptsAllowed {
|
|
||||||
setImage(shieldsPartiallyUpImage, for: .normal)
|
|
||||||
} else {
|
} else {
|
||||||
setImage(shieldsUpImage, for: .normal)
|
setImage(shieldsUpImage, for: .normal)
|
||||||
|
|
||||||
|
if isEnabled {
|
||||||
|
policyImageView.isHidden = false
|
||||||
|
policyImageView.image = ScriptPolicy.iconRepresentation(forPolicyType: currentPolicy.policyType, configuration: ScriptPolicy.IconConfiguration(
|
||||||
|
size: policyImageSize,
|
||||||
|
foregroundColor: .label,
|
||||||
|
backgroundColor: .clear
|
||||||
|
))
|
||||||
|
} else {
|
||||||
|
policyImageView.isHidden = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -51,10 +51,16 @@ class ScriptPolicyViewController: UIViewController, UICollectionViewDelegate
|
|||||||
let scriptPolicyRegistry = UICollectionView.CellRegistration<UICollectionViewListCell, Item> { (listCell, indexPath, item) in
|
let scriptPolicyRegistry = UICollectionView.CellRegistration<UICollectionViewListCell, Item> { (listCell, indexPath, item) in
|
||||||
guard case let Item.policy(policyType) = item else { return }
|
guard case let Item.policy(policyType) = item else { return }
|
||||||
|
|
||||||
|
let iconSize = CGSize(width: 24.0, height: 24.0)
|
||||||
|
|
||||||
var config = listCell.defaultContentConfiguration()
|
var config = listCell.defaultContentConfiguration()
|
||||||
config.text = ScriptPolicy.title(forPolicyType: policyType)
|
config.text = ScriptPolicy.title(forPolicyType: policyType)
|
||||||
config.secondaryText = ScriptPolicy.localizedDescription(forPolicyType: policyType)
|
config.secondaryText = ScriptPolicy.localizedDescription(forPolicyType: policyType)
|
||||||
config.image = ScriptPolicy.iconRepresentation(forPolicyType: policyType, size: CGSize(width: 24.0, height: 24.0))
|
config.image = ScriptPolicy.iconRepresentation(forPolicyType: policyType, configuration: ScriptPolicy.IconConfiguration(
|
||||||
|
size: iconSize,
|
||||||
|
foregroundColor: .white,
|
||||||
|
backgroundColor: .black
|
||||||
|
))
|
||||||
|
|
||||||
config.textProperties.font = UIFont.boldSystemFont(ofSize: 14.0)
|
config.textProperties.font = UIFont.boldSystemFont(ofSize: 14.0)
|
||||||
|
|
||||||
|
|||||||
@@ -6,10 +6,11 @@
|
|||||||
//
|
//
|
||||||
|
|
||||||
#import <Foundation/Foundation.h>
|
#import <Foundation/Foundation.h>
|
||||||
|
#import <QuartzCore/QuartzCore.h>
|
||||||
|
|
||||||
NS_ASSUME_NONNULL_BEGIN
|
NS_ASSUME_NONNULL_BEGIN
|
||||||
|
|
||||||
@class UIImage;
|
@class UIImage, UIColor;
|
||||||
|
|
||||||
typedef NS_ENUM(NSInteger, SBRScriptOriginPolicyType) {
|
typedef NS_ENUM(NSInteger, SBRScriptOriginPolicyType) {
|
||||||
SBRScriptOriginPolicyTypeAlpha,
|
SBRScriptOriginPolicyTypeAlpha,
|
||||||
@@ -19,6 +20,15 @@ typedef NS_ENUM(NSInteger, SBRScriptOriginPolicyType) {
|
|||||||
SBRScriptOriginPolicyTypeEcho,
|
SBRScriptOriginPolicyTypeEcho,
|
||||||
} NS_SWIFT_NAME(ScriptPolicy.PolicyType);
|
} NS_SWIFT_NAME(ScriptPolicy.PolicyType);
|
||||||
|
|
||||||
|
NS_SWIFT_NAME(ScriptPolicy.IconConfiguration)
|
||||||
|
@interface SBRScriptPolicyIconConfiguration : NSObject
|
||||||
|
@property (nonatomic, readwrite) CGSize size;
|
||||||
|
@property (nonatomic, strong, nullable) UIColor *foregroundColor;
|
||||||
|
@property (nonatomic, strong, nullable) UIColor *backgroundColor;
|
||||||
|
|
||||||
|
- (instancetype)initWithSize:(CGSize)size foregroundColor:(nullable UIColor *)foregroundColor backgroundColor:(nullable UIColor *)backgroundColor;
|
||||||
|
@end
|
||||||
|
|
||||||
NS_SWIFT_NAME(ScriptPolicy)
|
NS_SWIFT_NAME(ScriptPolicy)
|
||||||
@interface SBRScriptPolicy : NSObject <NSSecureCoding>
|
@interface SBRScriptPolicy : NSObject <NSSecureCoding>
|
||||||
@property (nonatomic, copy) NSString *origin;
|
@property (nonatomic, copy) NSString *origin;
|
||||||
@@ -30,8 +40,8 @@ NS_SWIFT_NAME(ScriptPolicy)
|
|||||||
+ (NSString *)localizedDescriptionForPolicyType:(SBRScriptOriginPolicyType)policyType
|
+ (NSString *)localizedDescriptionForPolicyType:(SBRScriptOriginPolicyType)policyType
|
||||||
NS_SWIFT_NAME(localizedDescription(forPolicyType:));
|
NS_SWIFT_NAME(localizedDescription(forPolicyType:));
|
||||||
|
|
||||||
+ (UIImage *)iconRepresentationForPolicyType:(SBRScriptOriginPolicyType)policyType withSize:(CGSize)size
|
+ (UIImage *)iconRepresentationForPolicyType:(SBRScriptOriginPolicyType)policyType withConfiguration:(SBRScriptPolicyIconConfiguration *)configuration
|
||||||
NS_SWIFT_NAME(iconRepresentation(forPolicyType:size:));
|
NS_SWIFT_NAME(iconRepresentation(forPolicyType:configuration:));
|
||||||
|
|
||||||
- (instancetype)initWithSecurityOrigin:(NSString *)origin policyType:(SBRScriptOriginPolicyType)policyType;
|
- (instancetype)initWithSecurityOrigin:(NSString *)origin policyType:(SBRScriptOriginPolicyType)policyType;
|
||||||
|
|
||||||
|
|||||||
@@ -10,6 +10,10 @@
|
|||||||
// For icon drawing
|
// For icon drawing
|
||||||
#import <UIKit/UIKit.h>
|
#import <UIKit/UIKit.h>
|
||||||
|
|
||||||
|
static CGFloat RoundToScale(CGFloat v, CGFloat s) {
|
||||||
|
return round(v * s) / s;
|
||||||
|
}
|
||||||
|
|
||||||
@implementation SBRScriptPolicy
|
@implementation SBRScriptPolicy
|
||||||
|
|
||||||
+ (NSSet<NSString *> *)_commonCDNOrigins {
|
+ (NSSet<NSString *> *)_commonCDNOrigins {
|
||||||
@@ -70,17 +74,20 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
+ (UIImage *)iconRepresentationForPolicyType:(SBRScriptOriginPolicyType)policyType withSize:(CGSize)size
|
+ (UIImage *)iconRepresentationForPolicyType:(SBRScriptOriginPolicyType)policyType withConfiguration:(nonnull SBRScriptPolicyIconConfiguration *)configuration
|
||||||
{
|
{
|
||||||
|
const CGSize size = [configuration size];
|
||||||
UIFont *font = [UIFont boldSystemFontOfSize:size.height - 2];
|
UIFont *font = [UIFont boldSystemFontOfSize:size.height - 2];
|
||||||
NSDictionary<NSAttributedStringKey, id> *attrs = @{
|
NSDictionary<NSAttributedStringKey, id> *attrs = @{
|
||||||
NSFontAttributeName : font,
|
NSFontAttributeName : font,
|
||||||
NSForegroundColorAttributeName : [UIColor whiteColor]
|
NSForegroundColorAttributeName : [configuration foregroundColor] ?: [UIColor whiteColor],
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const CGFloat scale = UIScreen.mainScreen.scale;
|
||||||
const CGRect rect = (CGRect) { .origin = CGPointZero, .size = size };
|
const CGRect rect = (CGRect) { .origin = CGPointZero, .size = size };
|
||||||
UIGraphicsBeginImageContextWithOptions(size, NO, UIScreen.mainScreen.scale);
|
UIGraphicsBeginImageContextWithOptions(size, NO, scale);
|
||||||
|
|
||||||
|
[([configuration backgroundColor] ?: [UIColor blackColor]) setFill];
|
||||||
UIBezierPath *backgroundPath = [UIBezierPath bezierPathWithRoundedRect:rect cornerRadius:4.0];
|
UIBezierPath *backgroundPath = [UIBezierPath bezierPathWithRoundedRect:rect cornerRadius:4.0];
|
||||||
[backgroundPath fill];
|
[backgroundPath fill];
|
||||||
|
|
||||||
@@ -98,7 +105,10 @@
|
|||||||
character = @"𝝴"; break;
|
character = @"𝝴"; break;
|
||||||
}
|
}
|
||||||
|
|
||||||
const CGSize charSize = [character sizeWithAttributes:attrs];
|
CGSize charSize = [character sizeWithAttributes:attrs];
|
||||||
|
charSize.width = RoundToScale(charSize.width, scale);
|
||||||
|
charSize.height = RoundToScale(charSize.height, scale);
|
||||||
|
|
||||||
const CGRect charRect = (CGRect) {
|
const CGRect charRect = (CGRect) {
|
||||||
.origin = (CGPoint) {
|
.origin = (CGPoint) {
|
||||||
.x = (size.width - charSize.width) / 2,
|
.x = (size.width - charSize.width) / 2,
|
||||||
@@ -203,3 +213,18 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
|
@implementation SBRScriptPolicyIconConfiguration
|
||||||
|
|
||||||
|
- (instancetype)initWithSize:(CGSize)size foregroundColor:(nullable UIColor *)foregroundColor backgroundColor:(nullable UIColor *)backgroundColor
|
||||||
|
{
|
||||||
|
if (self = [super init]) {
|
||||||
|
_size = size;
|
||||||
|
_foregroundColor = foregroundColor;
|
||||||
|
_backgroundColor = backgroundColor;
|
||||||
|
}
|
||||||
|
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
||||||
|
|||||||
@@ -711,7 +711,7 @@
|
|||||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||||
IPHONEOS_DEPLOYMENT_TARGET = 14.0;
|
IPHONEOS_DEPLOYMENT_TARGET = 15.0;
|
||||||
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
|
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
|
||||||
MTL_FAST_MATH = YES;
|
MTL_FAST_MATH = YES;
|
||||||
ONLY_ACTIVE_ARCH = YES;
|
ONLY_ACTIVE_ARCH = YES;
|
||||||
@@ -767,7 +767,7 @@
|
|||||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||||
IPHONEOS_DEPLOYMENT_TARGET = 14.0;
|
IPHONEOS_DEPLOYMENT_TARGET = 15.0;
|
||||||
MTL_ENABLE_DEBUG_INFO = NO;
|
MTL_ENABLE_DEBUG_INFO = NO;
|
||||||
MTL_FAST_MATH = YES;
|
MTL_FAST_MATH = YES;
|
||||||
SDKROOT = iphoneos.internal;
|
SDKROOT = iphoneos.internal;
|
||||||
@@ -789,12 +789,10 @@
|
|||||||
CURRENT_PROJECT_VERSION = 2;
|
CURRENT_PROJECT_VERSION = 2;
|
||||||
DEVELOPMENT_TEAM = DQQH5H6GBD;
|
DEVELOPMENT_TEAM = DQQH5H6GBD;
|
||||||
INFOPLIST_FILE = "App/Supporting Files/Info.plist";
|
INFOPLIST_FILE = "App/Supporting Files/Info.plist";
|
||||||
IPHONEOS_DEPLOYMENT_TARGET = 14.0;
|
|
||||||
LD_RUNPATH_SEARCH_PATHS = (
|
LD_RUNPATH_SEARCH_PATHS = (
|
||||||
"$(inherited)",
|
"$(inherited)",
|
||||||
"@executable_path/Frameworks",
|
"@executable_path/Frameworks",
|
||||||
);
|
);
|
||||||
MACOSX_DEPLOYMENT_TARGET = 10.15;
|
|
||||||
MARKETING_VERSION = 2.0;
|
MARKETING_VERSION = 2.0;
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = net.buzzert.rosslerattix;
|
PRODUCT_BUNDLE_IDENTIFIER = net.buzzert.rosslerattix;
|
||||||
PRODUCT_NAME = "rossler attix";
|
PRODUCT_NAME = "rossler attix";
|
||||||
@@ -819,12 +817,10 @@
|
|||||||
CURRENT_PROJECT_VERSION = 2;
|
CURRENT_PROJECT_VERSION = 2;
|
||||||
DEVELOPMENT_TEAM = DQQH5H6GBD;
|
DEVELOPMENT_TEAM = DQQH5H6GBD;
|
||||||
INFOPLIST_FILE = "App/Supporting Files/Info.plist";
|
INFOPLIST_FILE = "App/Supporting Files/Info.plist";
|
||||||
IPHONEOS_DEPLOYMENT_TARGET = 14.0;
|
|
||||||
LD_RUNPATH_SEARCH_PATHS = (
|
LD_RUNPATH_SEARCH_PATHS = (
|
||||||
"$(inherited)",
|
"$(inherited)",
|
||||||
"@executable_path/Frameworks",
|
"@executable_path/Frameworks",
|
||||||
);
|
);
|
||||||
MACOSX_DEPLOYMENT_TARGET = 10.15;
|
|
||||||
MARKETING_VERSION = 2.0;
|
MARKETING_VERSION = 2.0;
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = net.buzzert.rosslerattix;
|
PRODUCT_BUNDLE_IDENTIFIER = net.buzzert.rosslerattix;
|
||||||
PRODUCT_NAME = "rossler attix";
|
PRODUCT_NAME = "rossler attix";
|
||||||
|
|||||||
@@ -32,8 +32,8 @@
|
|||||||
</TestAction>
|
</TestAction>
|
||||||
<LaunchAction
|
<LaunchAction
|
||||||
buildConfiguration = "Debug"
|
buildConfiguration = "Debug"
|
||||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
selectedDebuggerIdentifier = ""
|
||||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
selectedLauncherIdentifier = "Xcode.IDEFoundation.Launcher.PosixSpawn"
|
||||||
launchStyle = "0"
|
launchStyle = "0"
|
||||||
useCustomWorkingDirectory = "NO"
|
useCustomWorkingDirectory = "NO"
|
||||||
ignoresPersistentStateOnLaunch = "NO"
|
ignoresPersistentStateOnLaunch = "NO"
|
||||||
|
|||||||
Reference in New Issue
Block a user