mirror of
https://github.com/MacPass/MacPass.git
synced 2025-12-22 08:09:29 +00:00
Use DuckDuckGo favicon service (#1073)
* Use DuckDuckGo favicon service There are multiple ways of how favicon of a website can be published: - Have a `favicon.ico` file under the website root - Set through `<link rel="shortcut icon" href="..." />` tag - Set through `<link rel="icon" href="..." />` tag, or - Set through platform-specific tags like `<link rel="apple-touch-icon" href="..." />` Current implementation only supports first option, which does not work in many cases. Instead of implementing favicon fetching logic from scratch, favicon fetching services can be used. There are multiple of them, e.g.: - https://icons.duckduckgo.com/ip3/www.google.com.ico - https://www.google.com/s2/favicons?domain=www.google.com This change switched from fetching favicon from the original host to DuckDuckGo. * Create UX for favicon download method preferences * Add preferences for favicon download method * Adjust preferences window location Also, sort localized resources Co-authored-by: Alex Rakov <alexander-rakov@users.noreply.github.com>
This commit is contained in:
@@ -19,13 +19,14 @@
|
||||
<outlet property="preventUniversalClipboardSupportCheckButton" destination="nqZ-rB-mFS" id="sbx-rl-reT"/>
|
||||
<outlet property="rememberKeyFileCheckButton" destination="bSt-Wf-FNZ" id="aQm-EA-yAN"/>
|
||||
<outlet property="reopenLastDatabase" destination="530" id="878"/>
|
||||
<outlet property="faviconDownloadMethodPopup" destination="OfU-6f-oTU" id="OfU-6f-oTU-outlet"/>
|
||||
<outlet property="view" destination="1" id="82"/>
|
||||
</connections>
|
||||
</customObject>
|
||||
<customObject id="-1" userLabel="First Responder" customClass="FirstResponder"/>
|
||||
<customObject id="-3" userLabel="Application" customClass="NSObject"/>
|
||||
<customView translatesAutoresizingMaskIntoConstraints="NO" id="1">
|
||||
<rect key="frame" x="0.0" y="0.0" width="411" height="547"/>
|
||||
<rect key="frame" x="0.0" y="0.0" width="406" height="669"/>
|
||||
<subviews>
|
||||
<box autoresizesSubviews="NO" verticalHuggingPriority="500" borderType="line" title="Security" translatesAutoresizingMaskIntoConstraints="NO" id="465">
|
||||
<rect key="frame" x="17" y="16" width="377" height="381"/>
|
||||
@@ -208,7 +209,7 @@
|
||||
</constraints>
|
||||
</box>
|
||||
<box autoresizesSubviews="NO" verticalHuggingPriority="500" borderType="line" title="File Handling" translatesAutoresizingMaskIntoConstraints="NO" id="888">
|
||||
<rect key="frame" x="17" y="399" width="377" height="128"/>
|
||||
<rect key="frame" x="17" y="529" width="372" height="128"/>
|
||||
<view key="contentView" id="cpg-tt-SHE">
|
||||
<rect key="frame" x="3" y="3" width="371" height="110"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
@@ -273,18 +274,71 @@
|
||||
<constraint firstItem="530" firstAttribute="top" secondItem="888" secondAttribute="top" constant="25" id="w7t-Jm-kXg"/>
|
||||
</constraints>
|
||||
</box>
|
||||
<box autoresizesSubviews="NO" verticalHuggingPriority="500" borderType="line" title="Network" translatesAutoresizingMaskIntoConstraints="NO" id="wD1-ag-7V5">
|
||||
<rect key="frame" x="17" y="16" width="372" height="125"/>
|
||||
<view key="contentView" id="bQD-ZX-d0i">
|
||||
<rect key="frame" x="3" y="3" width="366" height="109"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<subviews>
|
||||
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="fl5-Xu-nZP">
|
||||
<rect key="frame" x="14" y="81" width="113" height="16"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="height" constant="16" id="kK7-bB-zKY"/>
|
||||
</constraints>
|
||||
<textFieldCell key="cell" lineBreakMode="clipping" title="Favicon download" id="YGj-dH-duz">
|
||||
<font key="font" metaFont="system"/>
|
||||
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
</textField>
|
||||
<textField autoresizesSubviews="NO" verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" setsMaxLayoutWidthAtFirstLayout="YES" translatesAutoresizingMaskIntoConstraints="NO" id="MWj-9m-uGk">
|
||||
<rect key="frame" x="18" y="13" width="330" height="56"/>
|
||||
<textFieldCell key="cell" sendsActionOnEndEditing="YES" id="DaG-1a-SET">
|
||||
<font key="font" metaFont="message" size="11"/>
|
||||
<string key="title">By default web site icon is downloaded directly from entry's host URL. For some websites it doesn't work and you might prefer using 3rdparty APIs. In this case only host from the URL will be used to get the icon from selected service.</string>
|
||||
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
</textField>
|
||||
<popUpButton verticalHuggingPriority="750" horizontalCompressionResistancePriority="749" translatesAutoresizingMaskIntoConstraints="NO" id="OfU-6f-oTU">
|
||||
<rect key="frame" x="131" y="76" width="147" height="25"/>
|
||||
<popUpButtonCell key="cell" type="push" bezelStyle="rounded" alignment="left" lineBreakMode="truncatingTail" borderStyle="borderAndBezel" imageScaling="proportionallyDown" inset="2" id="mdi-Go-1bJ">
|
||||
<behavior key="behavior" lightByBackground="YES" lightByGray="YES"/>
|
||||
<font key="font" metaFont="system"/>
|
||||
<menu key="menu" id="Xnp-a8-ePw"/>
|
||||
</popUpButtonCell>
|
||||
</popUpButton>
|
||||
</subviews>
|
||||
<constraints>
|
||||
<constraint firstAttribute="trailing" relation="greaterThanOrEqual" secondItem="OfU-6f-oTU" secondAttribute="trailing" constant="16" id="0Wl-LS-ePD"/>
|
||||
<constraint firstItem="OfU-6f-oTU" firstAttribute="centerY" secondItem="fl5-Xu-nZP" secondAttribute="centerY" id="R81-Ij-pdy"/>
|
||||
<constraint firstItem="OfU-6f-oTU" firstAttribute="leading" secondItem="fl5-Xu-nZP" secondAttribute="trailing" constant="8" id="XS0-fl-B2Z"/>
|
||||
</constraints>
|
||||
</view>
|
||||
<constraints>
|
||||
<constraint firstItem="MWj-9m-uGk" firstAttribute="leading" secondItem="bQD-ZX-d0i" secondAttribute="leading" constant="20" id="1AE-Eu-ceQ"/>
|
||||
<constraint firstItem="fl5-Xu-nZP" firstAttribute="top" secondItem="wD1-ag-7V5" secondAttribute="top" constant="26" id="OK9-PR-DfC"/>
|
||||
<constraint firstItem="MWj-9m-uGk" firstAttribute="top" secondItem="fl5-Xu-nZP" secondAttribute="bottom" constant="12" id="Udz-22-4O1"/>
|
||||
<constraint firstAttribute="trailing" secondItem="MWj-9m-uGk" secondAttribute="trailing" constant="20" id="hA0-ra-UeU"/>
|
||||
<constraint firstItem="fl5-Xu-nZP" firstAttribute="leading" secondItem="bQD-ZX-d0i" secondAttribute="leading" constant="16" id="hzo-40-wxR"/>
|
||||
<constraint firstAttribute="bottom" secondItem="MWj-9m-uGk" secondAttribute="bottom" constant="12" id="k80-DD-Y5l"/>
|
||||
</constraints>
|
||||
</box>
|
||||
</subviews>
|
||||
<constraints>
|
||||
<constraint firstItem="465" firstAttribute="leading" secondItem="1" secondAttribute="leading" constant="20" symbolic="YES" id="475"/>
|
||||
<constraint firstAttribute="trailing" secondItem="465" secondAttribute="trailing" constant="20" symbolic="YES" id="525"/>
|
||||
<constraint firstItem="888" firstAttribute="leading" secondItem="1" secondAttribute="leading" constant="20" symbolic="YES" id="891"/>
|
||||
<constraint firstAttribute="trailing" secondItem="888" secondAttribute="trailing" constant="20" symbolic="YES" id="893"/>
|
||||
<constraint firstItem="888" firstAttribute="top" secondItem="1" secondAttribute="top" constant="20" symbolic="YES" id="903"/>
|
||||
<constraint firstAttribute="width" relation="greaterThanOrEqual" constant="400" id="918"/>
|
||||
<constraint firstAttribute="bottom" secondItem="465" secondAttribute="bottom" constant="20" symbolic="YES" id="uwq-az-XwJ"/>
|
||||
<constraint firstItem="465" firstAttribute="top" secondItem="cpg-tt-SHE" secondAttribute="bottom" constant="5" id="wyH-HB-i2U"/>
|
||||
<constraint firstItem="wD1-ag-7V5" firstAttribute="leading" secondItem="1" secondAttribute="leading" constant="20" id="3kp-Uf-fyC"/>
|
||||
<constraint firstItem="wD1-ag-7V5" firstAttribute="bottom" secondItem="1" secondAttribute="bottom" constant="-20" id="EeW-K0-jec"/>
|
||||
<constraint firstItem="wD1-ag-7V5" firstAttribute="top" secondItem="465" secondAttribute="bottom" constant="8" id="FsW-LX-Drs"/>
|
||||
<constraint firstItem="888" firstAttribute="top" secondItem="1" secondAttribute="top" constant="12" id="ZMP-Lv-rQh"/>
|
||||
<constraint firstAttribute="trailing" secondItem="wD1-ag-7V5" secondAttribute="trailing" constant="20" id="ccK-FL-7Wx"/>
|
||||
<constraint firstItem="465" firstAttribute="top" secondItem="888" secondAttribute="bottom" constant="6" id="wyH-HB-i2U"/>
|
||||
</constraints>
|
||||
<point key="canvasLocation" x="-458" y="-295"/>
|
||||
<point key="canvasLocation" x="-461" y="-156.5"/>
|
||||
</customView>
|
||||
</objects>
|
||||
</document>
|
||||
|
||||
@@ -37,5 +37,6 @@
|
||||
@property (strong) IBOutlet NSButton *enableAutosaveCheckButton;
|
||||
@property (strong) IBOutlet NSButton *rememberKeyFileCheckButton;
|
||||
@property (strong) IBOutlet NSPopUpButton *fileChangeStrategyPopup;
|
||||
@property (strong) IBOutlet NSPopUpButton *faviconDownloadMethodPopup;
|
||||
|
||||
@end
|
||||
|
||||
@@ -56,6 +56,19 @@
|
||||
[self.enableAutosaveCheckButton bind:NSValueBinding toObject:defaultsController withKeyPath:[MPSettingsHelper defaultControllerPathForKey:kMPSettingsKeyEnableAutosave] options:nil];
|
||||
[self.rememberKeyFileCheckButton bind:NSValueBinding toObject:defaultsController withKeyPath:[MPSettingsHelper defaultControllerPathForKey:kMPSettingsKeyRememberKeyFilesForDatabases] options:nil];
|
||||
|
||||
/* Favicon download method menu */
|
||||
NSDictionary *faviconDownloadMethodDict = @{ @(MPFaviconDownloadMethodDirect) : NSLocalizedString(@"FAVICON_DOWNLOAD_METHOD_DIRECT", @"Favicon download method: directly download from the host"),
|
||||
@(MPFaviconDownloadMethodDuckDuckGo) : NSLocalizedString(@"FAVICON_DOWNLOAD_METHOD_DUCKDUCKGO", @"Favicon download method: use DuckDuckGo's favicon fetching service"),
|
||||
@(MPFaviconDownloadMethodGoogle) : NSLocalizedString(@"FAVICON_DOWNLOAD_METHOD_GOOGLE", @"Favicon download method: use Google's favicon fetching service"),
|
||||
};
|
||||
[self.faviconDownloadMethodPopup.menu removeAllItems];
|
||||
for(NSNumber *key in faviconDownloadMethodDict) {
|
||||
NSMenuItem *item = [[NSMenuItem alloc] initWithTitle:faviconDownloadMethodDict[key] action:NULL keyEquivalent:@""];
|
||||
item.tag = key.integerValue;
|
||||
[self.faviconDownloadMethodPopup.menu addItem:item];
|
||||
}
|
||||
[self.faviconDownloadMethodPopup bind:NSSelectedTagBinding toObject:defaultsController withKeyPath:[MPSettingsHelper defaultControllerPathForKey:kMPSettingsKeyFaviconDownloadMethod] options:nil];
|
||||
|
||||
/* File Change Strategy Menu */
|
||||
NSDictionary *fileChangeStragegyDict = @{ @(MPFileChangeStrategyAsk) : NSLocalizedString(@"FILE_CHANGE_STRATEGY_ASK", @"External file change strategy option: ask what to do"),
|
||||
@(MPFileChangeStrategyUseOther) : NSLocalizedString(@"FILE_CHANGE_STRATEGY_USE_OTHER", @"External file change strategy option: Use the changed file and discard local changes"),
|
||||
@@ -69,6 +82,6 @@
|
||||
[self.fileChangeStrategyPopup.menu addItem:item];
|
||||
}
|
||||
[self.fileChangeStrategyPopup bind:NSSelectedTagBinding toObject:defaultsController withKeyPath:[MPSettingsHelper defaultControllerPathForKey:kMPSettingsKeyFileChangeStrategy] options:nil];
|
||||
|
||||
|
||||
}
|
||||
@end
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
//
|
||||
|
||||
#import "MPIconHelper.h"
|
||||
#import "MPSettingsHelper.h"
|
||||
#import "KeePassKit/KeePassKit.h"
|
||||
|
||||
@implementation MPIconHelper
|
||||
@@ -44,11 +45,11 @@
|
||||
dispatch_once(&onceToken, ^{
|
||||
NSDictionary *imageNames = [MPIconHelper availableIconNames];
|
||||
NSMutableArray *mutableIcons = [[NSMutableArray alloc] initWithCapacity:imageNames.count];
|
||||
|
||||
|
||||
NSArray *sortedImageNames = [imageNames.allKeys sortedArrayUsingComparator:^NSComparisonResult(id obj1, id obj2) {
|
||||
return [imageNames[obj1] compare:imageNames[obj2]];
|
||||
}];
|
||||
|
||||
|
||||
for(NSNumber *iconNumber in sortedImageNames) {
|
||||
if(iconNumber.integerValue > MPCustomIconTypeBegin) {
|
||||
continue; // Skip all non-db Keys
|
||||
@@ -68,7 +69,7 @@
|
||||
static dispatch_once_t onceToken;
|
||||
dispatch_once(&onceToken, ^{
|
||||
NSDictionary *imageNames = [MPIconHelper availableIconNames];
|
||||
|
||||
|
||||
NSArray *sortedImageNames = [[imageNames allKeys] sortedArrayUsingComparator:^NSComparisonResult(id obj1, id obj2) {
|
||||
return [[imageNames objectForKey:obj1] compare:[imageNames objectForKey:obj2]];
|
||||
}];
|
||||
@@ -163,7 +164,7 @@
|
||||
@(MPIconAddEntry): @"addEntryTemplate",
|
||||
@(MPIconContextTriangle): @"contextTriangleTemplate",
|
||||
@(MPIconKeyboard): @"keyboardTemplate",
|
||||
|
||||
|
||||
@(MPIconExpiredEntry): NSImageNameCaution,
|
||||
@(MPIconExpiredGroup): NSImageNameCaution
|
||||
};
|
||||
@@ -177,14 +178,24 @@
|
||||
return; // no url, no handler so no need to do anything
|
||||
}
|
||||
|
||||
// default setting value is direct download
|
||||
NSString *urlString = [NSString stringWithFormat:@"%@://%@/favicon.ico", url.scheme, url.host ? url.host : @""];
|
||||
|
||||
MPFaviconDownloadMethod faviconDownloadMethod = (MPFaviconDownloadMethod)[NSUserDefaults.standardUserDefaults integerForKey:kMPSettingsKeyFaviconDownloadMethod];
|
||||
if (faviconDownloadMethod == MPFaviconDownloadMethodDuckDuckGo) {
|
||||
urlString = [NSString stringWithFormat:@"https://icons.duckduckgo.com/ip3/%@.ico", url.host ? url.host : @""];
|
||||
}
|
||||
else if (faviconDownloadMethod == MPFaviconDownloadMethodGoogle) {
|
||||
urlString = [NSString stringWithFormat:@"https://www.google.com/s2/favicons?domain=%@", url.host ? url.host : @""];
|
||||
}
|
||||
|
||||
NSURL *favIconURL = [NSURL URLWithString:urlString];
|
||||
if(!favIconURL) {
|
||||
/* call the handler with nil data */
|
||||
handler(nil);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
NSURLSessionTask *task = [NSURLSession.sharedSession dataTaskWithURL:favIconURL completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
|
||||
if(error) {
|
||||
handler(nil);
|
||||
|
||||
@@ -91,11 +91,14 @@ APPKIT_EXTERN NSString *const kMPSettingsKeyHideIncopatiblePluginsWarning; // D
|
||||
APPKIT_EXTERN NSString *const kMPSettingsKeyAllowRemoteFetchOfPluginRepository; // Allow the download of the plugin repository file
|
||||
APPKIT_EXTERN NSString *const kMPSettingsKeyPluginHideAksForRemoveConnectionPermission;
|
||||
|
||||
/* Network */
|
||||
APPKIT_EXTERN NSString *const kMPSettingsKeyFaviconDownloadMethod;
|
||||
|
||||
typedef NS_ENUM(NSUInteger, MPFileChangeStrategy) {
|
||||
MPFileChangeStrategyAsk,
|
||||
MPFileChangeStrategyKeepMine,
|
||||
MPFileChangeStrategyUseOther,
|
||||
MPFileChangeStrategyMerge
|
||||
MPFileChangeStrategyMerge,
|
||||
};
|
||||
|
||||
typedef NS_ENUM(NSUInteger, MPDoubleClickURLAction) {
|
||||
@@ -108,6 +111,12 @@ typedef NS_ENUM(NSUInteger, MPDoubleClickTitleAction) {
|
||||
MPDoubleClickTitleActionIgnore,
|
||||
};
|
||||
|
||||
typedef NS_ENUM(NSUInteger, MPFaviconDownloadMethod) {
|
||||
MPFaviconDownloadMethodDirect,
|
||||
MPFaviconDownloadMethodDuckDuckGo,
|
||||
MPFaviconDownloadMethodGoogle,
|
||||
};
|
||||
|
||||
/* Password Generation */
|
||||
APPKIT_EXTERN NSString *const kMPSettingsKeyCopyGeneratedPasswordToClipboard;
|
||||
APPKIT_EXTERN NSString *const kMPSettingsKeyDefaultPasswordLength;
|
||||
|
||||
@@ -87,6 +87,8 @@ NSString *const kMPSettingsKeyDisabledPlugins = @"Disabl
|
||||
NSString *const kMPSettingsKeyHideIncopatiblePluginsWarning = @"HideIncopatiblePluginsWarning";
|
||||
NSString *const kMPSettingsKeyAllowRemoteFetchOfPluginRepository = @"AllowRemoteFetchOfPluginRepository";
|
||||
|
||||
NSString *const kMPSettingsKeyFaviconDownloadMethod = @"FaviconDownloadMethod";
|
||||
|
||||
/* Deprecated */
|
||||
NSString *const kMPDeprecatedSettingsKeyRememberKeyFilesForDatabases = @"kMPSettingsKeyRememberKeyFilesForDatabases";
|
||||
NSString *const kMPDeprecatedSettingsKeyLastDatabasePath = @"MPLastDatabasePath";
|
||||
@@ -164,7 +166,8 @@ NSString *const kMPDepricatedSettingsKeyAutotypeHideAccessibiltyWarning = @"Au
|
||||
kMPSettingsKeyLoadIncompatiblePlugins: @NO,
|
||||
kMPSettingsKeyQuitOnLastWindowClose: @NO,
|
||||
kMPSettingsKeyEnableAutosave: @YES,
|
||||
kMPSettingsKeyHideAfterCopyToClipboard: @NO
|
||||
kMPSettingsKeyHideAfterCopyToClipboard: @NO,
|
||||
kMPSettingsKeyFaviconDownloadMethod: @(MPFaviconDownloadMethodDirect) // Download directly from host
|
||||
};
|
||||
});
|
||||
return standardDefaults;
|
||||
@@ -203,17 +206,17 @@ NSString *const kMPDepricatedSettingsKeyAutotypeHideAccessibiltyWarning = @"Au
|
||||
/*
|
||||
MacPass < 0.4 did use compare: for the entry table view,
|
||||
this was changed in 0.4 to localizedCaseInsensitiveCompare:
|
||||
|
||||
|
||||
MacPass < 0.5.2 did use parent.name for group names,
|
||||
this was changed in 0.6. to parent.title
|
||||
|
||||
|
||||
*/
|
||||
NSData *descriptorData = [NSUserDefaults.standardUserDefaults dataForKey:kMPSettingsKeyEntryTableSortDescriptors];
|
||||
if(!descriptorData) {
|
||||
return; // No user defaults
|
||||
}
|
||||
NSArray *sortDescriptors = [NSKeyedUnarchiver unarchiveObjectWithData:descriptorData];
|
||||
|
||||
|
||||
for(NSSortDescriptor *descriptor in sortDescriptors) {
|
||||
/* Brute force, just kill the settings if they might cause trouble */
|
||||
if(descriptor.selector == @selector(compare:)
|
||||
@@ -291,7 +294,7 @@ NSString *const kMPDepricatedSettingsKeyAutotypeHideAccessibiltyWarning = @"Au
|
||||
if(oldValue != [[self _standardDefaults][kMPDepricatedSettingsKeyLoadUnsecurePlugins] boolValue]) {
|
||||
[NSUserDefaults.standardUserDefaults setBool:oldValue forKey:kMPSettingsKeyLoadUnsecurePlugins];
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@@ -15,10 +15,10 @@
|
||||
<customObject id="-3" userLabel="Application" customClass="NSObject"/>
|
||||
<window title="Window" allowsToolTipsWhenApplicationIsInactive="NO" autorecalculatesKeyViewLoop="NO" visibleAtLaunch="NO" animationBehavior="default" id="1">
|
||||
<windowStyleMask key="styleMask" titled="YES" closable="YES" miniaturizable="YES"/>
|
||||
<rect key="contentRect" x="196" y="240" width="400" height="300"/>
|
||||
<rect key="contentRect" x="196" y="240" width="400" height="700"/>
|
||||
<rect key="screenRect" x="0.0" y="0.0" width="2560" height="1417"/>
|
||||
<view key="contentView" id="2">
|
||||
<rect key="frame" x="0.0" y="0.0" width="400" height="300"/>
|
||||
<rect key="frame" x="0.0" y="0.0" width="400" height="700"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
</view>
|
||||
<point key="canvasLocation" x="67" y="-65"/>
|
||||
|
||||
@@ -382,6 +382,15 @@
|
||||
/* The master key was changed by an external program! */
|
||||
"EXTERN_CHANGE_OF_MASTERKEY" = "Master key was changed by another program";
|
||||
|
||||
/* Direct download */
|
||||
"FAVICON_DOWNLOAD_METHOD_DIRECT" = "Direct download";
|
||||
|
||||
/* DuckDuckGo */
|
||||
"FAVICON_DOWNLOAD_METHOD_DUCKDUCKGO" = "DuckDuckGo";
|
||||
|
||||
/* Google */
|
||||
"FAVICON_DOWNLOAD_METHOD_GOOGLE" = "Google";
|
||||
|
||||
/* External file change strategy option: ask what to do */
|
||||
"FILE_CHANGE_STRATEGY_ASK" = "Ask";
|
||||
|
||||
@@ -837,4 +846,3 @@
|
||||
|
||||
/* Yesterday */
|
||||
"YESTERDAY" = "Yesterday";
|
||||
|
||||
|
||||
Reference in New Issue
Block a user