Compare commits
26 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5db294bdb3 | ||
|
|
fee7bc7401 | ||
|
|
21968f4ba6 | ||
|
|
8582c934c2 | ||
|
|
7091e2ee1b | ||
|
|
d5d455ee57 | ||
|
|
e6ae06798b | ||
|
|
1cae4c754b | ||
|
|
93ad86e63c | ||
|
|
cf74dc5cc2 | ||
|
|
981bdb3ab4 | ||
|
|
9bea8bcbdf | ||
|
|
363d6f6639 | ||
|
|
eb1632cb62 | ||
|
|
73fadaef7f | ||
|
|
60200f6302 | ||
|
|
cce8db5c48 | ||
|
|
6f3da5ccf0 | ||
|
|
52c87eaeca | ||
|
|
1dccdd0a3c | ||
|
|
eb8d10ed05 | ||
|
|
d9e5f77bee | ||
|
|
60f60d087e | ||
|
|
df97dec2fe | ||
|
|
3bac8d9e0a | ||
|
|
3fa7e1e8a1 |
@@ -9,10 +9,12 @@ build_project:
|
|||||||
- "( ./lib/bin/build_libsodium-macos clean && ./lib/bin/build_libsodium-macos )"
|
- "( ./lib/bin/build_libsodium-macos clean && ./lib/bin/build_libsodium-macos )"
|
||||||
- "( ./lib/bin/build_libjson-c-macos clean && ./lib/bin/build_libjson-c-macos )"
|
- "( ./lib/bin/build_libjson-c-macos clean && ./lib/bin/build_libjson-c-macos )"
|
||||||
- "( cd ./platform-independent/c/cli && ./clean && targets=all ./build && ./mpw-tests && ./mpw-cli-tests )"
|
- "( cd ./platform-independent/c/cli && ./clean && targets=all ./build && ./mpw-tests && ./mpw-cli-tests )"
|
||||||
- "( export JAVA_HOME=$(java_home -Fv 10 || java_home -Fv 9* ) && ./gradlew --stacktrace clean test )"
|
- "( ./gradlew --stacktrace --info clean test )"
|
||||||
- "( xcodebuild -workspace platform-darwin/MasterPassword.xcworkspace -configuration 'Test' -scheme 'MasterPassword iOS' -sdk iphonesimulator clean build )"
|
- "( cd platform-darwin && pod install )"
|
||||||
- "( xcodebuild -workspace platform-darwin/MasterPassword.xcworkspace -configuration 'Test' -scheme 'MasterPassword macOS' clean build )"
|
- "( xcodebuild -workspace platform-darwin/MasterPassword.xcworkspace -configuration 'Release' -scheme 'MasterPassword iOS' -sdk iphonesimulator clean build )"
|
||||||
|
- "( xcodebuild -workspace platform-darwin/MasterPassword.xcworkspace -configuration 'Release' -scheme 'MasterPassword macOS' clean build )"
|
||||||
tags:
|
tags:
|
||||||
- brew
|
- brew
|
||||||
- java_9
|
- java
|
||||||
- xcode_9
|
- cocoapods
|
||||||
|
- xcode
|
||||||
|
|||||||
2
platform-darwin/External/Pearl
vendored
2
platform-darwin/External/Pearl
vendored
Submodule platform-darwin/External/Pearl updated: 72de3d1b49...fbb8e6f94b
@@ -49,7 +49,6 @@
|
|||||||
93D39A5FF670957C0AF8298D /* MPSiteCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 93D39DEA995041A13DC9CAF7 /* MPSiteCell.m */; };
|
93D39A5FF670957C0AF8298D /* MPSiteCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 93D39DEA995041A13DC9CAF7 /* MPSiteCell.m */; };
|
||||||
93D39A8EA1C49CE43B63F47B /* PearlUICollectionView.m in Sources */ = {isa = PBXBuildFile; fileRef = 93D39D8A953779B35403AF6E /* PearlUICollectionView.m */; };
|
93D39A8EA1C49CE43B63F47B /* PearlUICollectionView.m in Sources */ = {isa = PBXBuildFile; fileRef = 93D39D8A953779B35403AF6E /* PearlUICollectionView.m */; };
|
||||||
93D39AA4A0BE66A872CCC02E /* NSPersistentStore+PearlMigration.h in Headers */ = {isa = PBXBuildFile; fileRef = 93D397F4BAFFF7CF3F1B21A4 /* NSPersistentStore+PearlMigration.h */; };
|
93D39AA4A0BE66A872CCC02E /* NSPersistentStore+PearlMigration.h in Headers */ = {isa = PBXBuildFile; fileRef = 93D397F4BAFFF7CF3F1B21A4 /* NSPersistentStore+PearlMigration.h */; };
|
||||||
93D39B429C67A62E29DC02DA /* MPRootSegue.m in Sources */ = {isa = PBXBuildFile; fileRef = 93D399493FEDDE74DD1A0C15 /* MPRootSegue.m */; };
|
|
||||||
93D39B76DD5AB108BA8928E8 /* UIScrollView+PearlAdjustInsets.h in Headers */ = {isa = PBXBuildFile; fileRef = 93D39DE2CB351D4E3789462B /* UIScrollView+PearlAdjustInsets.h */; };
|
93D39B76DD5AB108BA8928E8 /* UIScrollView+PearlAdjustInsets.h in Headers */ = {isa = PBXBuildFile; fileRef = 93D39DE2CB351D4E3789462B /* UIScrollView+PearlAdjustInsets.h */; };
|
||||||
93D39B842AB9A5D072810D76 /* NSError+PearlFullDescription.h in Headers */ = {isa = PBXBuildFile; fileRef = 93D398C95847261903D781D3 /* NSError+PearlFullDescription.h */; };
|
93D39B842AB9A5D072810D76 /* NSError+PearlFullDescription.h in Headers */ = {isa = PBXBuildFile; fileRef = 93D398C95847261903D781D3 /* NSError+PearlFullDescription.h */; };
|
||||||
93D39B8F90F58A5D158DDBA3 /* MPSitesViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 93D3924EE15017F8A12CB436 /* MPSitesViewController.m */; };
|
93D39B8F90F58A5D158DDBA3 /* MPSitesViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 93D3924EE15017F8A12CB436 /* MPSitesViewController.m */; };
|
||||||
@@ -175,7 +174,6 @@
|
|||||||
DA67461018DE7F0C00DFE240 /* Exo2.0-Bold.otf in Resources */ = {isa = PBXBuildFile; fileRef = DA67460C18DE7F0C00DFE240 /* Exo2.0-Bold.otf */; };
|
DA67461018DE7F0C00DFE240 /* Exo2.0-Bold.otf in Resources */ = {isa = PBXBuildFile; fileRef = DA67460C18DE7F0C00DFE240 /* Exo2.0-Bold.otf */; };
|
||||||
DA69540617D975D900BF294E /* icon_gears.png in Resources */ = {isa = PBXBuildFile; fileRef = DABD37841711E29500CF925C /* icon_gears.png */; };
|
DA69540617D975D900BF294E /* icon_gears.png in Resources */ = {isa = PBXBuildFile; fileRef = DABD37841711E29500CF925C /* icon_gears.png */; };
|
||||||
DA69540717D975D900BF294E /* icon_gears@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = DABD37851711E29500CF925C /* icon_gears@2x.png */; };
|
DA69540717D975D900BF294E /* icon_gears@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = DABD37851711E29500CF925C /* icon_gears@2x.png */; };
|
||||||
DA72BD7B19C1510C00E6ACFE /* UIView+FontScale.m in Sources */ = {isa = PBXBuildFile; fileRef = DACE2F6719BA6A2A0010F92E /* UIView+FontScale.m */; };
|
|
||||||
DA72E2302453B91700676D4F /* WebKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DA72E22F2453B91700676D4F /* WebKit.framework */; };
|
DA72E2302453B91700676D4F /* WebKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DA72E22F2453B91700676D4F /* WebKit.framework */; };
|
||||||
DA73049D194E022700E72520 /* ui_spinner.png in Resources */ = {isa = PBXBuildFile; fileRef = DABD36511711E29400CF925C /* ui_spinner.png */; };
|
DA73049D194E022700E72520 /* ui_spinner.png in Resources */ = {isa = PBXBuildFile; fileRef = DABD36511711E29400CF925C /* ui_spinner.png */; };
|
||||||
DA73049E194E022700E72520 /* ui_spinner@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = DABD36521711E29400CF925C /* ui_spinner@2x.png */; };
|
DA73049E194E022700E72520 /* ui_spinner@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = DABD36521711E29400CF925C /* ui_spinner@2x.png */; };
|
||||||
@@ -476,7 +474,6 @@
|
|||||||
93D391943675426839501BB8 /* MPLogsViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPLogsViewController.h; sourceTree = "<group>"; };
|
93D391943675426839501BB8 /* MPLogsViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPLogsViewController.h; sourceTree = "<group>"; };
|
||||||
93D391AA32F24290C424438E /* NSNotificationCenter+PearlEasyCleanup.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSNotificationCenter+PearlEasyCleanup.h"; sourceTree = "<group>"; };
|
93D391AA32F24290C424438E /* NSNotificationCenter+PearlEasyCleanup.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSNotificationCenter+PearlEasyCleanup.h"; sourceTree = "<group>"; };
|
||||||
93D39246FC21C6E63E35D615 /* UICollectionView+PearlReloadItems.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UICollectionView+PearlReloadItems.h"; sourceTree = "<group>"; };
|
93D39246FC21C6E63E35D615 /* UICollectionView+PearlReloadItems.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UICollectionView+PearlReloadItems.h"; sourceTree = "<group>"; };
|
||||||
93D3924D6F77E6BF41AC32D3 /* MPRootSegue.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPRootSegue.h; sourceTree = "<group>"; };
|
|
||||||
93D3924EE15017F8A12CB436 /* MPSitesViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPSitesViewController.m; sourceTree = "<group>"; };
|
93D3924EE15017F8A12CB436 /* MPSitesViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPSitesViewController.m; sourceTree = "<group>"; };
|
||||||
93D392876BE5C011DE73B43F /* MPPopdownSegue.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPPopdownSegue.h; sourceTree = "<group>"; };
|
93D392876BE5C011DE73B43F /* MPPopdownSegue.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPPopdownSegue.h; sourceTree = "<group>"; };
|
||||||
93D392C5A6572DB0EB5B82C8 /* mpw-types.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "mpw-types.c"; sourceTree = "<group>"; };
|
93D392C5A6572DB0EB5B82C8 /* mpw-types.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "mpw-types.c"; sourceTree = "<group>"; };
|
||||||
@@ -505,7 +502,6 @@
|
|||||||
93D398C95847261903D781D3 /* NSError+PearlFullDescription.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSError+PearlFullDescription.h"; sourceTree = "<group>"; };
|
93D398C95847261903D781D3 /* NSError+PearlFullDescription.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSError+PearlFullDescription.h"; sourceTree = "<group>"; };
|
||||||
93D3990D850D76A94C6B7A4D /* mpw-algorithm.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "mpw-algorithm.h"; sourceTree = "<group>"; };
|
93D3990D850D76A94C6B7A4D /* mpw-algorithm.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "mpw-algorithm.h"; sourceTree = "<group>"; };
|
||||||
93D3990E0CD1B5CF9FBB2C07 /* MPWebViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPWebViewController.m; sourceTree = "<group>"; };
|
93D3990E0CD1B5CF9FBB2C07 /* MPWebViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPWebViewController.m; sourceTree = "<group>"; };
|
||||||
93D399493FEDDE74DD1A0C15 /* MPRootSegue.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPRootSegue.m; sourceTree = "<group>"; };
|
|
||||||
93D3995B1D4DCE5A30D882BA /* MPCoachmarkViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPCoachmarkViewController.m; sourceTree = "<group>"; };
|
93D3995B1D4DCE5A30D882BA /* MPCoachmarkViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPCoachmarkViewController.m; sourceTree = "<group>"; };
|
||||||
93D39975CE5AEC99E3F086C7 /* MPSiteCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPSiteCell.h; sourceTree = "<group>"; };
|
93D39975CE5AEC99E3F086C7 /* MPSiteCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPSiteCell.h; sourceTree = "<group>"; };
|
||||||
93D3999693660C89A7465F4E /* MPCoachmarkViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPCoachmarkViewController.h; sourceTree = "<group>"; };
|
93D3999693660C89A7465F4E /* MPCoachmarkViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPCoachmarkViewController.h; sourceTree = "<group>"; };
|
||||||
@@ -2784,8 +2780,6 @@
|
|||||||
93D39B050DD5F55E9794EFD4 /* MPPopdownSegue.m */,
|
93D39B050DD5F55E9794EFD4 /* MPPopdownSegue.m */,
|
||||||
DABD3BEA1711E2DC00CF925C /* MPPreferencesViewController.h */,
|
DABD3BEA1711E2DC00CF925C /* MPPreferencesViewController.h */,
|
||||||
DABD3BEB1711E2DC00CF925C /* MPPreferencesViewController.m */,
|
DABD3BEB1711E2DC00CF925C /* MPPreferencesViewController.m */,
|
||||||
93D3924D6F77E6BF41AC32D3 /* MPRootSegue.h */,
|
|
||||||
93D399493FEDDE74DD1A0C15 /* MPRootSegue.m */,
|
|
||||||
93D39730673227EFF6DEFF19 /* MPSetupViewController.h */,
|
93D39730673227EFF6DEFF19 /* MPSetupViewController.h */,
|
||||||
93D39A28369954D147E239BA /* MPSetupViewController.m */,
|
93D39A28369954D147E239BA /* MPSetupViewController.m */,
|
||||||
93D39975CE5AEC99E3F086C7 /* MPSiteCell.h */,
|
93D39975CE5AEC99E3F086C7 /* MPSiteCell.h */,
|
||||||
@@ -3166,7 +3160,7 @@
|
|||||||
DA5BFA42147E415C00F98B1E /* Resources */,
|
DA5BFA42147E415C00F98B1E /* Resources */,
|
||||||
DA6556E314D55F3000841C99 /* Run Script: GIT version -> Info.plist */,
|
DA6556E314D55F3000841C99 /* Run Script: GIT version -> Info.plist */,
|
||||||
4A87858EE3659604089E2F9F /* [CP] Embed Pods Frameworks */,
|
4A87858EE3659604089E2F9F /* [CP] Embed Pods Frameworks */,
|
||||||
DA3C4EB32439438B00A6C4A8 /* Upload Sentry dSYM */,
|
DA3C4EB32439438B00A6C4A8 /* Sentry dSYM Upload */,
|
||||||
);
|
);
|
||||||
buildRules = (
|
buildRules = (
|
||||||
);
|
);
|
||||||
@@ -3523,7 +3517,7 @@
|
|||||||
shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
|
shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
|
||||||
showEnvVarsInLog = 0;
|
showEnvVarsInLog = 0;
|
||||||
};
|
};
|
||||||
DA3C4EB32439438B00A6C4A8 /* Upload Sentry dSYM */ = {
|
DA3C4EB32439438B00A6C4A8 /* Sentry dSYM Upload */ = {
|
||||||
isa = PBXShellScriptBuildPhase;
|
isa = PBXShellScriptBuildPhase;
|
||||||
buildActionMask = 8;
|
buildActionMask = 8;
|
||||||
files = (
|
files = (
|
||||||
@@ -3531,15 +3525,16 @@
|
|||||||
inputFileListPaths = (
|
inputFileListPaths = (
|
||||||
);
|
);
|
||||||
inputPaths = (
|
inputPaths = (
|
||||||
|
"${DWARF_DSYM_FOLDER_PATH}/${DWARF_DSYM_FILE_NAME}/Contents/Resources/DWARF/${TARGET_NAME}",
|
||||||
);
|
);
|
||||||
name = "Upload Sentry dSYM";
|
name = "Sentry dSYM Upload";
|
||||||
outputFileListPaths = (
|
outputFileListPaths = (
|
||||||
);
|
);
|
||||||
outputPaths = (
|
outputPaths = (
|
||||||
);
|
);
|
||||||
runOnlyForDeploymentPostprocessing = 1;
|
runOnlyForDeploymentPostprocessing = 1;
|
||||||
shellPath = "/bin/sh -e";
|
shellPath = "/bin/sh -e";
|
||||||
shellScript = "if hash sentry-cli 2>/dev/null; then\n if ! ERROR=$(SENTRY_ORG=lyndir SENTRY_PROJECT=masterpassword-ios sentry-cli upload-dif --log-level info \"$DWARF_DSYM_FOLDER_PATH\" 2>&1 >/dev/null); then\n echo >&2 \"warning: sentry-cli: $ERROR\"\n fi\nelse\n echo >&2 \"warning: sentry-cli not installed: try brew install getsentry/tools/sentry-cli\"\nfi\n";
|
shellScript = "if ! hash sentry-cli 2>/dev/null; then\n echo >&2 \"error: sentry-cli not installed. Try brew install getsentry/tools/sentry-cli\"\n exit 1\nfi\n\nSENTRY_ORG=lyndir SENTRY_PROJECT=masterpassword-ios sentry-cli upload-dif --log-level info \"$DWARF_DSYM_FOLDER_PATH\"\n";
|
||||||
showEnvVarsInLog = 0;
|
showEnvVarsInLog = 0;
|
||||||
};
|
};
|
||||||
DA6556E314D55F3000841C99 /* Run Script: GIT version -> Info.plist */ = {
|
DA6556E314D55F3000841C99 /* Run Script: GIT version -> Info.plist */ = {
|
||||||
@@ -3642,7 +3637,6 @@
|
|||||||
93D399D7E08A142776A74CB8 /* MPOverlayViewController.m in Sources */,
|
93D399D7E08A142776A74CB8 /* MPOverlayViewController.m in Sources */,
|
||||||
DA46021D23D5E30B00398FF4 /* MPSecrets.m in Sources */,
|
DA46021D23D5E30B00398FF4 /* MPSecrets.m in Sources */,
|
||||||
93D39A27F2506C6FEEF9C588 /* MPAlgorithmV2.m in Sources */,
|
93D39A27F2506C6FEEF9C588 /* MPAlgorithmV2.m in Sources */,
|
||||||
93D39B429C67A62E29DC02DA /* MPRootSegue.m in Sources */,
|
|
||||||
93D392FD5E2052F7D7DB3774 /* NSString+MPMarkDown.m in Sources */,
|
93D392FD5E2052F7D7DB3774 /* NSString+MPMarkDown.m in Sources */,
|
||||||
93D395B715D15F2B56F2A2EE /* mpw-types.c in Sources */,
|
93D395B715D15F2B56F2A2EE /* mpw-types.c in Sources */,
|
||||||
93D39943D01E70DAC3B0DF76 /* mpw-util.c in Sources */,
|
93D39943D01E70DAC3B0DF76 /* mpw-util.c in Sources */,
|
||||||
@@ -3688,7 +3682,6 @@
|
|||||||
DAFE4A2E15039824003ABA7C /* PearlStrings.m in Sources */,
|
DAFE4A2E15039824003ABA7C /* PearlStrings.m in Sources */,
|
||||||
DAFE4A3015039824003ABA7C /* PearlStringUtils.m in Sources */,
|
DAFE4A3015039824003ABA7C /* PearlStringUtils.m in Sources */,
|
||||||
DAFE4A3715039824003ABA7C /* PearlKeyChain.m in Sources */,
|
DAFE4A3715039824003ABA7C /* PearlKeyChain.m in Sources */,
|
||||||
DA72BD7B19C1510C00E6ACFE /* UIView+FontScale.m in Sources */,
|
|
||||||
DA250A17195665A100AC23F1 /* UITableView+PearlReloadItems.m in Sources */,
|
DA250A17195665A100AC23F1 /* UITableView+PearlReloadItems.m in Sources */,
|
||||||
DAFE4A4115039824003ABA7C /* PearlArrayTVC.m in Sources */,
|
DAFE4A4115039824003ABA7C /* PearlArrayTVC.m in Sources */,
|
||||||
DAFE4A4315039824003ABA7C /* PearlBoxView.m in Sources */,
|
DAFE4A4315039824003ABA7C /* PearlBoxView.m in Sources */,
|
||||||
|
|||||||
@@ -73,6 +73,13 @@
|
|||||||
identifier = "com.apple.dt.IDEFoundation.CurrentLocationScenarioIdentifier"
|
identifier = "com.apple.dt.IDEFoundation.CurrentLocationScenarioIdentifier"
|
||||||
referenceType = "1">
|
referenceType = "1">
|
||||||
</LocationScenarioReference>
|
</LocationScenarioReference>
|
||||||
|
<EnvironmentVariables>
|
||||||
|
<EnvironmentVariable
|
||||||
|
key = "TERM"
|
||||||
|
value = "color"
|
||||||
|
isEnabled = "YES">
|
||||||
|
</EnvironmentVariable>
|
||||||
|
</EnvironmentVariables>
|
||||||
</LaunchAction>
|
</LaunchAction>
|
||||||
<ProfileAction
|
<ProfileAction
|
||||||
buildConfiguration = "Debug"
|
buildConfiguration = "Debug"
|
||||||
|
|||||||
@@ -2329,7 +2329,7 @@
|
|||||||
DAD9B5EE1762CA3A001835F9 /* Copy LoginHelper */,
|
DAD9B5EE1762CA3A001835F9 /* Copy LoginHelper */,
|
||||||
DA6556E314D55F3000841C99 /* Run Script: GIT version -> Info.plist */,
|
DA6556E314D55F3000841C99 /* Run Script: GIT version -> Info.plist */,
|
||||||
43E5966C8C236E86824DDADE /* [CP] Embed Pods Frameworks */,
|
43E5966C8C236E86824DDADE /* [CP] Embed Pods Frameworks */,
|
||||||
DA3C4EB2243941AE00A6C4A8 /* Upload Sentry dSYM */,
|
DA3C4EB2243941AE00A6C4A8 /* Sentry dSYM Upload */,
|
||||||
);
|
);
|
||||||
buildRules = (
|
buildRules = (
|
||||||
);
|
);
|
||||||
@@ -2585,7 +2585,7 @@
|
|||||||
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-MasterPassword-macOS/Pods-MasterPassword-macOS-frameworks.sh\"\n";
|
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-MasterPassword-macOS/Pods-MasterPassword-macOS-frameworks.sh\"\n";
|
||||||
showEnvVarsInLog = 0;
|
showEnvVarsInLog = 0;
|
||||||
};
|
};
|
||||||
DA3C4EB2243941AE00A6C4A8 /* Upload Sentry dSYM */ = {
|
DA3C4EB2243941AE00A6C4A8 /* Sentry dSYM Upload */ = {
|
||||||
isa = PBXShellScriptBuildPhase;
|
isa = PBXShellScriptBuildPhase;
|
||||||
buildActionMask = 8;
|
buildActionMask = 8;
|
||||||
files = (
|
files = (
|
||||||
@@ -2593,15 +2593,16 @@
|
|||||||
inputFileListPaths = (
|
inputFileListPaths = (
|
||||||
);
|
);
|
||||||
inputPaths = (
|
inputPaths = (
|
||||||
|
"${DWARF_DSYM_FOLDER_PATH}/${DWARF_DSYM_FILE_NAME}/Contents/Resources/DWARF/${TARGET_NAME}",
|
||||||
);
|
);
|
||||||
name = "Upload Sentry dSYM";
|
name = "Sentry dSYM Upload";
|
||||||
outputFileListPaths = (
|
outputFileListPaths = (
|
||||||
);
|
);
|
||||||
outputPaths = (
|
outputPaths = (
|
||||||
);
|
);
|
||||||
runOnlyForDeploymentPostprocessing = 1;
|
runOnlyForDeploymentPostprocessing = 1;
|
||||||
shellPath = "/bin/sh -e";
|
shellPath = "/bin/sh -e";
|
||||||
shellScript = "if hash sentry-cli 2>/dev/null; then\n if ! ERROR=$(SENTRY_ORG=lyndir SENTRY_PROJECT=masterpassword-macos sentry-cli upload-dif --log-level info \"$DWARF_DSYM_FOLDER_PATH\" 2>&1 >/dev/null); then\n echo >&2 \"warning: sentry-cli: $ERROR\"\n fi\nelse\n echo >&2 \"warning: sentry-cli not installed: try brew install getsentry/tools/sentry-cli\"\nfi\n";
|
shellScript = "if ! hash sentry-cli 2>/dev/null; then\n echo >&2 \"error: sentry-cli not installed. Try brew install getsentry/tools/sentry-cli\"\n exit 1\nfi\n\nSENTRY_ORG=lyndir SENTRY_PROJECT=masterpassword-macos sentry-cli upload-dif --log-level info \"$DWARF_DSYM_FOLDER_PATH\"\n";
|
||||||
showEnvVarsInLog = 0;
|
showEnvVarsInLog = 0;
|
||||||
};
|
};
|
||||||
DA4EF9CB19FD4B600032ECB5 /* Run Script: genassets */ = {
|
DA4EF9CB19FD4B600032ECB5 /* Run Script: genassets */ = {
|
||||||
|
|||||||
@@ -59,6 +59,17 @@
|
|||||||
ReferencedContainer = "container:MasterPassword-macOS.xcodeproj">
|
ReferencedContainer = "container:MasterPassword-macOS.xcodeproj">
|
||||||
</BuildableReference>
|
</BuildableReference>
|
||||||
</BuildableProductRunnable>
|
</BuildableProductRunnable>
|
||||||
|
<EnvironmentVariables>
|
||||||
|
<EnvironmentVariable
|
||||||
|
key = "TERM"
|
||||||
|
value = "color"
|
||||||
|
isEnabled = "YES">
|
||||||
|
</EnvironmentVariable>
|
||||||
|
</EnvironmentVariables>
|
||||||
|
<LocationScenarioReference
|
||||||
|
identifier = "com.apple.dt.IDEFoundation.CurrentLocationScenarioIdentifier"
|
||||||
|
referenceType = "1">
|
||||||
|
</LocationScenarioReference>
|
||||||
</LaunchAction>
|
</LaunchAction>
|
||||||
<ProfileAction
|
<ProfileAction
|
||||||
buildConfiguration = "Debug"
|
buildConfiguration = "Debug"
|
||||||
|
|||||||
@@ -59,6 +59,17 @@
|
|||||||
ReferencedContainer = "container:MasterPassword-macOS.xcodeproj">
|
ReferencedContainer = "container:MasterPassword-macOS.xcodeproj">
|
||||||
</BuildableReference>
|
</BuildableReference>
|
||||||
</BuildableProductRunnable>
|
</BuildableProductRunnable>
|
||||||
|
<EnvironmentVariables>
|
||||||
|
<EnvironmentVariable
|
||||||
|
key = "TERM"
|
||||||
|
value = "color"
|
||||||
|
isEnabled = "YES">
|
||||||
|
</EnvironmentVariable>
|
||||||
|
</EnvironmentVariables>
|
||||||
|
<LocationScenarioReference
|
||||||
|
identifier = "com.apple.dt.IDEFoundation.CurrentLocationScenarioIdentifier"
|
||||||
|
referenceType = "1">
|
||||||
|
</LocationScenarioReference>
|
||||||
</LaunchAction>
|
</LaunchAction>
|
||||||
<ProfileAction
|
<ProfileAction
|
||||||
buildConfiguration = "Release"
|
buildConfiguration = "Release"
|
||||||
|
|||||||
@@ -85,6 +85,13 @@
|
|||||||
identifier = "com.apple.dt.IDEFoundation.CurrentLocationScenarioIdentifier"
|
identifier = "com.apple.dt.IDEFoundation.CurrentLocationScenarioIdentifier"
|
||||||
referenceType = "1">
|
referenceType = "1">
|
||||||
</LocationScenarioReference>
|
</LocationScenarioReference>
|
||||||
|
<EnvironmentVariables>
|
||||||
|
<EnvironmentVariable
|
||||||
|
key = "TERM"
|
||||||
|
value = "color"
|
||||||
|
isEnabled = "YES">
|
||||||
|
</EnvironmentVariable>
|
||||||
|
</EnvironmentVariables>
|
||||||
</LaunchAction>
|
</LaunchAction>
|
||||||
<ProfileAction
|
<ProfileAction
|
||||||
buildConfiguration = "Release"
|
buildConfiguration = "Release"
|
||||||
|
|||||||
@@ -60,6 +60,17 @@
|
|||||||
ReferencedContainer = "container:MasterPassword-macOS.xcodeproj">
|
ReferencedContainer = "container:MasterPassword-macOS.xcodeproj">
|
||||||
</BuildableReference>
|
</BuildableReference>
|
||||||
</BuildableProductRunnable>
|
</BuildableProductRunnable>
|
||||||
|
<EnvironmentVariables>
|
||||||
|
<EnvironmentVariable
|
||||||
|
key = "TERM"
|
||||||
|
value = "color"
|
||||||
|
isEnabled = "YES">
|
||||||
|
</EnvironmentVariable>
|
||||||
|
</EnvironmentVariables>
|
||||||
|
<LocationScenarioReference
|
||||||
|
identifier = "com.apple.dt.IDEFoundation.CurrentLocationScenarioIdentifier"
|
||||||
|
referenceType = "1">
|
||||||
|
</LocationScenarioReference>
|
||||||
</LaunchAction>
|
</LaunchAction>
|
||||||
<ProfileAction
|
<ProfileAction
|
||||||
buildConfiguration = "Debug"
|
buildConfiguration = "Debug"
|
||||||
|
|||||||
@@ -28,3 +28,14 @@ target 'MasterPassword-macOS' do
|
|||||||
pod 'KCOrderedAccessorFix'
|
pod 'KCOrderedAccessorFix'
|
||||||
pod 'JRSwizzle'
|
pod 'JRSwizzle'
|
||||||
end
|
end
|
||||||
|
|
||||||
|
post_install do |installer|
|
||||||
|
installer.pods_project.targets.each do |target|
|
||||||
|
if target.name == 'Countly-iOS' || target.name == 'Countly-macOS'
|
||||||
|
target.build_configurations.each do |config|
|
||||||
|
config.build_settings['GCC_PREPROCESSOR_DEFINITIONS'] ||= ['$(inherited)']
|
||||||
|
config.build_settings['GCC_PREPROCESSOR_DEFINITIONS'] << 'COUNTLY_EXCLUDE_IDFA=1'
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|||||||
@@ -621,7 +621,7 @@ static NSOperationQueue *_mpwQueue = nil;
|
|||||||
|
|
||||||
- (NSString *)exportLoginForSite:(MPSiteEntity *)site usingKey:(MPKey *)key {
|
- (NSString *)exportLoginForSite:(MPSiteEntity *)site usingKey:(MPKey *)key {
|
||||||
|
|
||||||
if (!(site.type & MPSiteFeatureExportContent) || site.loginGenerated || ![site.loginName length])
|
if (site.loginGenerated || ![site.loginName length])
|
||||||
return nil;
|
return nil;
|
||||||
|
|
||||||
__block NSData *state = nil;
|
__block NSData *state = nil;
|
||||||
|
|||||||
@@ -117,7 +117,7 @@ PearlAssociatedObjectProperty( NSMutableArray*, ProductObservers, productObserve
|
|||||||
[self performPurchaseProductWithIdentifier:productIdentifier quantity:quantity];
|
[self performPurchaseProductWithIdentifier:productIdentifier quantity:quantity];
|
||||||
}]];
|
}]];
|
||||||
[controller addAction:[UIAlertAction actionWithTitle:@"Cancel" style:UIAlertActionStyleCancel handler:nil]];
|
[controller addAction:[UIAlertAction actionWithTitle:@"Cancel" style:UIAlertActionStyleCancel handler:nil]];
|
||||||
[self.navigationController presentViewController:controller animated:YES completion:nil];
|
[self.window.rootViewController presentViewController:controller animated:YES completion:nil];
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@@ -158,16 +158,16 @@ PearlAssociatedObjectProperty( NSMutableArray*, ProductObservers, productObserve
|
|||||||
|
|
||||||
- (void)request:(SKRequest *)request didFailWithError:(NSError *)error {
|
- (void)request:(SKRequest *)request didFailWithError:(NSError *)error {
|
||||||
|
|
||||||
MPError( error, @"StoreKit request (%@) failed.", request );
|
MPError( error, @"StoreKit request failed." );
|
||||||
|
|
||||||
#if TARGET_OS_IPHONE
|
#if TARGET_OS_IPHONE
|
||||||
PearlMainQueue( ^{
|
PearlMainQueue( ^{
|
||||||
UIAlertController *controller = [UIAlertController alertControllerWithTitle:@"Purchase Failed" message:
|
UIAlertController *controller = [UIAlertController alertControllerWithTitle:@"Purchase Failed" message:
|
||||||
strf( @"%@\n\n%@", error.localizedDescription,
|
strf( @"%@\n\n%@", error.localizedDescription,
|
||||||
@"Ensure you are online and try logging out and back into iTunes from your device's Settings." )
|
@"Could not reach Apple's iTunes Store. Make sure you're connected to the Internet and try again." )
|
||||||
preferredStyle:UIAlertControllerStyleAlert];
|
preferredStyle:UIAlertControllerStyleAlert];
|
||||||
[controller addAction:[UIAlertAction actionWithTitle:@"OK" style:UIAlertActionStyleCancel handler:nil]];
|
[controller addAction:[UIAlertAction actionWithTitle:@"OK" style:UIAlertActionStyleCancel handler:nil]];
|
||||||
[self.navigationController presentViewController:controller animated:YES completion:nil];
|
[self.window.rootViewController presentViewController:controller animated:YES completion:nil];
|
||||||
} );
|
} );
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
@@ -222,6 +222,17 @@ PearlAssociatedObjectProperty( NSMutableArray*, ProductObservers, productObserve
|
|||||||
MPError( transaction.error, @"Transaction failed: %@.", transaction.payment.productIdentifier );
|
MPError( transaction.error, @"Transaction failed: %@.", transaction.payment.productIdentifier );
|
||||||
[queue finishTransaction:transaction];
|
[queue finishTransaction:transaction];
|
||||||
|
|
||||||
|
#if TARGET_OS_IPHONE
|
||||||
|
PearlMainQueue( ^{
|
||||||
|
UIAlertController *controller = [UIAlertController alertControllerWithTitle:@"Purchase Failed" message:
|
||||||
|
strf( @"%@\n\n%@", transaction.error.localizedDescription,
|
||||||
|
@"Could not reach Apple's iTunes Store. Make sure you're connected to the Internet and try again." )
|
||||||
|
preferredStyle:UIAlertControllerStyleAlert];
|
||||||
|
[controller addAction:[UIAlertAction actionWithTitle:@"OK" style:UIAlertActionStyleCancel handler:nil]];
|
||||||
|
[self.window.rootViewController presentViewController:controller animated:YES completion:nil];
|
||||||
|
} );
|
||||||
|
#endif
|
||||||
|
|
||||||
SKProduct *product = self.products[transaction.payment.productIdentifier];
|
SKProduct *product = self.products[transaction.payment.productIdentifier];
|
||||||
[Countly.sharedInstance recordEvent:@"purchase" segmentation:@{
|
[Countly.sharedInstance recordEvent:@"purchase" segmentation:@{
|
||||||
@"id": product.productIdentifier,
|
@"id": product.productIdentifier,
|
||||||
|
|||||||
@@ -201,6 +201,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
@try {
|
@try {
|
||||||
|
[SentrySDK setUser:[[SentryUser alloc] initWithUserId:user.userID]];
|
||||||
[Countly.sharedInstance userLoggedIn:user.userID];
|
[Countly.sharedInstance userLoggedIn:user.userID];
|
||||||
|
|
||||||
[Countly.sharedInstance recordEvent:@"login" segmentation:@{
|
[Countly.sharedInstance recordEvent:@"login" segmentation:@{
|
||||||
@@ -248,18 +249,18 @@
|
|||||||
masterPassword = PearlAwait( ^(void (^setResult)(id)) {
|
masterPassword = PearlAwait( ^(void (^setResult)(id)) {
|
||||||
PearlMainQueue( ^{
|
PearlMainQueue( ^{
|
||||||
UIAlertController *controller = [UIAlertController alertControllerWithTitle:@"Enter Old Master Password" message:
|
UIAlertController *controller = [UIAlertController alertControllerWithTitle:@"Enter Old Master Password" message:
|
||||||
strf( @"Your old master password is required to migrate the stored password for %@", site.name )
|
strf( @"Your old master password is required to unlock the stored password for: <%@>", site.name )
|
||||||
preferredStyle:UIAlertControllerStyleAlert];
|
preferredStyle:UIAlertControllerStyleAlert];
|
||||||
[controller addTextFieldWithConfigurationHandler:nil];
|
[controller addTextFieldWithConfigurationHandler:nil];
|
||||||
[controller addAction:[UIAlertAction actionWithTitle:@"Migrate" style:UIAlertActionStyleDefault handler:
|
[controller addAction:[UIAlertAction actionWithTitle:@"Migrate" style:UIAlertActionStyleDefault handler:
|
||||||
^(UIAlertAction *_Nonnull action) {
|
^(UIAlertAction *_Nonnull action) {
|
||||||
setResult( controller.textFields.firstObject.text );
|
setResult( controller.textFields.firstObject.text );
|
||||||
}]];
|
}]];
|
||||||
[controller addAction:[UIAlertAction actionWithTitle:@"Don't Migrate" style:UIAlertActionStyleCancel handler:
|
[controller addAction:[UIAlertAction actionWithTitle:@"Leave It" style:UIAlertActionStyleCancel handler:
|
||||||
^(UIAlertAction *_Nonnull action) {
|
^(UIAlertAction *_Nonnull action) {
|
||||||
setResult( nil );
|
setResult( nil );
|
||||||
}]];
|
}]];
|
||||||
[self.navigationController presentViewController:controller animated:YES completion:nil];
|
[self.window.rootViewController presentViewController:controller animated:YES completion:nil];
|
||||||
} );
|
} );
|
||||||
} );
|
} );
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -20,7 +20,7 @@
|
|||||||
|
|
||||||
#if TARGET_OS_IPHONE
|
#if TARGET_OS_IPHONE
|
||||||
|
|
||||||
@interface MPAppDelegate_Shared : PearlAppDelegate
|
@interface MPAppDelegate_Shared : UIResponder<UIApplicationDelegate, PearlConfigDelegate>
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
|
|||||||
@@ -116,9 +116,8 @@ static MPAppDelegate_Shared *instance;
|
|||||||
if (self.activeUserOID == activeUserOID || [self.activeUserOID isEqual:activeUserOID])
|
if (self.activeUserOID == activeUserOID || [self.activeUserOID isEqual:activeUserOID])
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (self.key)
|
|
||||||
self.key = nil;
|
self.key = nil;
|
||||||
|
[SentrySDK setUser:nil];
|
||||||
[Countly.sharedInstance userLoggedOut];
|
[Countly.sharedInstance userLoggedOut];
|
||||||
|
|
||||||
self.activeUserOID = activeUserOID;
|
self.activeUserOID = activeUserOID;
|
||||||
|
|||||||
@@ -30,6 +30,7 @@
|
|||||||
- (id)managedObjectContextChanged:(void ( ^ )(NSDictionary<NSManagedObjectID *, NSString *> *affectedObjects))changedBlock;
|
- (id)managedObjectContextChanged:(void ( ^ )(NSDictionary<NSManagedObjectID *, NSString *> *affectedObjects))changedBlock;
|
||||||
|
|
||||||
- (MPFixableResult)findAndFixInconsistenciesSaveInContext:(NSManagedObjectContext *)context;
|
- (MPFixableResult)findAndFixInconsistenciesSaveInContext:(NSManagedObjectContext *)context;
|
||||||
|
- (void)retryCorruptStore;
|
||||||
- (void)deleteAndResetStore;
|
- (void)deleteAndResetStore;
|
||||||
|
|
||||||
/** @param completion The block to execute after adding the site, executed from the main thread with the new site in the main MOC. */
|
/** @param completion The block to execute after adding the site, executed from the main thread with the new site in the main MOC. */
|
||||||
|
|||||||
@@ -232,22 +232,27 @@ PearlAssociatedObjectProperty( NSNumber*, StoreCorrupted, storeCorrupted );
|
|||||||
}];
|
}];
|
||||||
} );
|
} );
|
||||||
|
|
||||||
|
|
||||||
// Create a new store coordinator.
|
// Create a new store coordinator.
|
||||||
NSError *error = nil;
|
NSError *error = nil;
|
||||||
NSURL *localStoreURL = [self localStoreURL];
|
NSURL *localStoreURL = [self localStoreURL];
|
||||||
if (![[NSFileManager defaultManager] createDirectoryAtURL:[localStoreURL URLByDeletingLastPathComponent]
|
if (![[NSFileManager defaultManager] createDirectoryAtURL:[localStoreURL URLByDeletingLastPathComponent]
|
||||||
withIntermediateDirectories:YES attributes:nil error:&error]) {
|
withIntermediateDirectories:YES attributes:nil error:&error]) {
|
||||||
MPError( error, @"Couldn't create our application support directory." );
|
MPError( error, @"Couldn't create our application support directory." );
|
||||||
|
PearlRemoveNotificationObserversFrom( self.mainManagedObjectContext );
|
||||||
|
self.mainManagedObjectContext = nil;
|
||||||
|
self.privateManagedObjectContext = nil;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (![self.storeCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:[self localStoreURL]
|
if (![self.storeCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:localStoreURL
|
||||||
options:@{
|
options:@{
|
||||||
NSMigratePersistentStoresAutomaticallyOption: @YES,
|
NSMigratePersistentStoresAutomaticallyOption: @YES,
|
||||||
NSInferMappingModelAutomaticallyOption : @YES,
|
NSInferMappingModelAutomaticallyOption : @YES,
|
||||||
STORE_OPTIONS
|
STORE_OPTIONS
|
||||||
} error:&error]) {
|
} error:&error]) {
|
||||||
MPError( error, @"Failed to open store." );
|
MPError( error, @"Failed to open store." );
|
||||||
|
PearlRemoveNotificationObserversFrom( self.mainManagedObjectContext );
|
||||||
|
self.mainManagedObjectContext = nil;
|
||||||
|
self.privateManagedObjectContext = nil;
|
||||||
self.storeCorrupted = @YES;
|
self.storeCorrupted = @YES;
|
||||||
[self handleCoordinatorError:error];
|
[self handleCoordinatorError:error];
|
||||||
return;
|
return;
|
||||||
@@ -274,6 +279,12 @@ PearlAssociatedObjectProperty( NSNumber*, StoreCorrupted, storeCorrupted );
|
|||||||
}];
|
}];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (void)retryCorruptStore {
|
||||||
|
|
||||||
|
self.storeCorrupted = @NO;
|
||||||
|
[self loadStore];
|
||||||
|
}
|
||||||
|
|
||||||
- (void)deleteAndResetStore {
|
- (void)deleteAndResetStore {
|
||||||
|
|
||||||
@synchronized (self) {
|
@synchronized (self) {
|
||||||
@@ -713,23 +724,31 @@ PearlAssociatedObjectProperty( NSNumber*, StoreCorrupted, storeCorrupted );
|
|||||||
MPMarshalledFile *exportFile = NULL;
|
MPMarshalledFile *exportFile = NULL;
|
||||||
@try {
|
@try {
|
||||||
inf( @"Exporting sites, %@, for user: %@", revealPasswords? @"revealing passwords": @"omitting passwords", user.userID );
|
inf( @"Exporting sites, %@, for user: %@", revealPasswords? @"revealing passwords": @"omitting passwords", user.userID );
|
||||||
|
NSString *masterPassword = askExportPassword( user.name );
|
||||||
|
if (!masterPassword) {
|
||||||
|
inf( @"Export cancelled." );
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
|
|
||||||
|
MPKey *key = [[MPKey alloc] initForFullName:user.name withMasterPassword:masterPassword];
|
||||||
exportUser = mpw_marshal_user( user.name.UTF8String,
|
exportUser = mpw_marshal_user( user.name.UTF8String,
|
||||||
mpw_masterKeyProvider_str( askExportPassword( user.name ).UTF8String ), user.algorithm.version );
|
mpw_masterKeyProvider_str( masterPassword.UTF8String ), user.algorithm.version );
|
||||||
exportUser->redacted = !revealPasswords;
|
exportUser->redacted = !revealPasswords;
|
||||||
exportUser->avatar = (unsigned int)user.avatar;
|
exportUser->avatar = (unsigned int)user.avatar;
|
||||||
exportUser->keyID = mpw_strdup( [user.keyID encodeHex].UTF8String );
|
exportUser->keyID = mpw_strdup( [user.keyID encodeHex].UTF8String );
|
||||||
exportUser->defaultType = user.defaultType;
|
exportUser->defaultType = user.defaultType;
|
||||||
exportUser->lastUsed = (time_t)user.lastUsed.timeIntervalSince1970;
|
exportUser->lastUsed = (time_t)user.lastUsed.timeIntervalSince1970;
|
||||||
|
|
||||||
for (MPSiteEntity *site in user.sites) {
|
for (MPSiteEntity *site in [user.sites sortedArrayUsingDescriptors:@[
|
||||||
|
[NSSortDescriptor sortDescriptorWithKey:@"name" ascending:YES]
|
||||||
|
]]) {
|
||||||
MPCounterValue counter = MPCounterValueInitial;
|
MPCounterValue counter = MPCounterValueInitial;
|
||||||
if ([site isKindOfClass:[MPGeneratedSiteEntity class]])
|
if ([site isKindOfClass:[MPGeneratedSiteEntity class]])
|
||||||
counter = ((MPGeneratedSiteEntity *)site).counter;
|
counter = ((MPGeneratedSiteEntity *)site).counter;
|
||||||
MPMarshalledSite *exportSite = mpw_marshal_site( exportUser,
|
MPMarshalledSite *exportSite = mpw_marshal_site( exportUser, site.name.UTF8String, site.type, counter, site.algorithm.version );
|
||||||
site.name.UTF8String, site.type, counter, site.algorithm.version );
|
exportSite->resultState = mpw_strdup( [site.algorithm exportPasswordForSite:site usingKey:key].UTF8String );
|
||||||
exportSite->resultState = mpw_strdup( [site.algorithm exportPasswordForSite:site usingKey:self.key].UTF8String );
|
exportSite->loginState = mpw_strdup( [site.algorithm exportLoginForSite:site usingKey:key].UTF8String );
|
||||||
exportSite->loginState = mpw_strdup( [site.algorithm exportLoginForSite:site usingKey:self.key].UTF8String );
|
exportSite->loginType = site.loginGenerated || !exportSite->loginState? MPResultTypeTemplateName: MPResultTypeStatefulPersonal;
|
||||||
exportSite->loginType = site.loginGenerated? MPResultTypeTemplateName: MPResultTypeStatefulPersonal;
|
|
||||||
exportSite->url = mpw_strdup( site.url.UTF8String );
|
exportSite->url = mpw_strdup( site.url.UTF8String );
|
||||||
exportSite->uses = (unsigned int)site.uses;
|
exportSite->uses = (unsigned int)site.uses;
|
||||||
exportSite->lastUsed = (time_t)site.lastUsed.timeIntervalSince1970;
|
exportSite->lastUsed = (time_t)site.lastUsed.timeIntervalSince1970;
|
||||||
|
|||||||
@@ -41,8 +41,9 @@ __END_DECLS
|
|||||||
\
|
\
|
||||||
if (__error && [[MPConfig get].sendInfo boolValue]) { \
|
if (__error && [[MPConfig get].sendInfo boolValue]) { \
|
||||||
SentryEvent *event = [[SentryEvent alloc] initWithLevel:kSentryLevelError]; \
|
SentryEvent *event = [[SentryEvent alloc] initWithLevel:kSentryLevelError]; \
|
||||||
event.message = strf(@"%@: %@", message_, [__error localizedDescription]); \
|
event.message = strf( message_ @": %@", ##__VA_ARGS__, [__error localizedDescription]); \
|
||||||
event.logger = @"MPError"; \
|
event.logger = @"MPError"; \
|
||||||
|
event.fingerprint = @[ message_, __error.domain, @(__error.code) ]; \
|
||||||
[SentrySDK captureEvent:event]; \
|
[SentrySDK captureEvent:event]; \
|
||||||
} \
|
} \
|
||||||
__error; \
|
__error; \
|
||||||
|
|||||||
@@ -12,9 +12,6 @@
|
|||||||
</customObject>
|
</customObject>
|
||||||
<customObject id="-1" userLabel="First Responder" customClass="FirstResponder"/>
|
<customObject id="-1" userLabel="First Responder" customClass="FirstResponder"/>
|
||||||
<customObject id="-3" userLabel="Application" customClass="NSObject"/>
|
<customObject id="-3" userLabel="Application" customClass="NSObject"/>
|
||||||
<menu title="AMainMenu" systemMenu="main" id="29">
|
|
||||||
<point key="canvasLocation" x="139" y="155"/>
|
|
||||||
</menu>
|
|
||||||
<customObject id="494" customClass="MPMacAppDelegate">
|
<customObject id="494" customClass="MPMacAppDelegate">
|
||||||
<connections>
|
<connections>
|
||||||
<outlet property="createUserItem" destination="757" id="763"/>
|
<outlet property="createUserItem" destination="757" id="763"/>
|
||||||
@@ -241,6 +238,9 @@
|
|||||||
</connections>
|
</connections>
|
||||||
</menuItem>
|
</menuItem>
|
||||||
</items>
|
</items>
|
||||||
|
<connections>
|
||||||
|
<outlet property="delegate" destination="494" id="Slu-zT-yO4"/>
|
||||||
|
</connections>
|
||||||
<point key="canvasLocation" x="140" y="23"/>
|
<point key="canvasLocation" x="140" y="23"/>
|
||||||
</menu>
|
</menu>
|
||||||
</objects>
|
</objects>
|
||||||
|
|||||||
@@ -21,9 +21,9 @@
|
|||||||
#import "MPSitesWindowController.h"
|
#import "MPSitesWindowController.h"
|
||||||
#import "MPInitialWindowController.h"
|
#import "MPInitialWindowController.h"
|
||||||
|
|
||||||
@interface MPMacAppDelegate : MPAppDelegate_Shared<NSApplicationDelegate>
|
@interface MPMacAppDelegate : MPAppDelegate_Shared<NSApplicationDelegate, NSMenuDelegate>
|
||||||
|
|
||||||
@property(nonatomic, strong) NSStatusItem *statusView;
|
@property(nonatomic, strong) NSStatusItem *statusItem;
|
||||||
@property(nonatomic, strong) MPSitesWindowController *sitesWindowController;
|
@property(nonatomic, strong) MPSitesWindowController *sitesWindowController;
|
||||||
@property(nonatomic, strong) MPInitialWindowController *initialWindowController;
|
@property(nonatomic, strong) MPInitialWindowController *initialWindowController;
|
||||||
@property(nonatomic, weak) IBOutlet NSMenuItem *lockItem;
|
@property(nonatomic, weak) IBOutlet NSMenuItem *lockItem;
|
||||||
|
|||||||
@@ -68,7 +68,7 @@ static OSStatus MPHotKeyHander(EventHandlerCallRef nextHandler, EventRef theEven
|
|||||||
|
|
||||||
@try {
|
@try {
|
||||||
// Sentry
|
// Sentry
|
||||||
[SentrySDK initWithOptions:@{
|
[SentrySDK startWithOptions:@{
|
||||||
@"dsn" : NilToNSNull( decrypt( sentryDSN ) ),
|
@"dsn" : NilToNSNull( decrypt( sentryDSN ) ),
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
@"debug" : @(YES),
|
@"debug" : @(YES),
|
||||||
@@ -80,7 +80,7 @@ static OSStatus MPHotKeyHander(EventHandlerCallRef nextHandler, EventRef theEven
|
|||||||
@"debug" : @(NO),
|
@"debug" : @(NO),
|
||||||
@"environment" : @"Private",
|
@"environment" : @"Private",
|
||||||
#endif
|
#endif
|
||||||
@"enabled" : [MPMacConfig get].sendInfo,
|
@"enabled" : @([[MPMacConfig get].sendInfo boolValue] || ![[MPMacConfig get].sendInfoDecided boolValue]),
|
||||||
@"enableAutoSessionTracking": @(YES),
|
@"enableAutoSessionTracking": @(YES),
|
||||||
}];
|
}];
|
||||||
[[PearlLogger get] registerListener:^BOOL(PearlLogMessage *message) {
|
[[PearlLogger get] registerListener:^BOOL(PearlLogMessage *message) {
|
||||||
@@ -158,12 +158,10 @@ static OSStatus MPHotKeyHander(EventHandlerCallRef nextHandler, EventRef theEven
|
|||||||
} forKeyPath:@"activeUser" options:0 context:nil];
|
} forKeyPath:@"activeUser" options:0 context:nil];
|
||||||
|
|
||||||
// Status item.
|
// Status item.
|
||||||
self.statusView = [[NSStatusBar systemStatusBar] statusItemWithLength:NSSquareStatusItemLength];
|
self.statusItem = [[NSStatusBar systemStatusBar] statusItemWithLength:NSSquareStatusItemLength];
|
||||||
self.statusView.image = [NSImage imageNamed:@"menu-icon"];
|
self.statusItem.menu = self.statusMenu;
|
||||||
self.statusView.image.template = YES;
|
self.statusItem.button.image = [NSImage imageNamed:@"menu-icon"];
|
||||||
self.statusView.menu = self.statusMenu;
|
self.statusItem.button.image.template = YES;
|
||||||
self.statusView.target = self;
|
|
||||||
self.statusView.action = @selector( showMenu );
|
|
||||||
|
|
||||||
PearlAddNotificationObserver( NSPersistentStoreCoordinatorStoresWillChangeNotification, self.storeCoordinator, nil,
|
PearlAddNotificationObserver( NSPersistentStoreCoordinatorStoresWillChangeNotification, self.storeCoordinator, nil,
|
||||||
^(id self, NSNotification *note) {
|
^(id self, NSNotification *note) {
|
||||||
@@ -502,7 +500,7 @@ static OSStatus MPHotKeyHander(EventHandlerCallRef nextHandler, EventRef theEven
|
|||||||
|
|
||||||
- (IBAction)showPopup:(id)sender {
|
- (IBAction)showPopup:(id)sender {
|
||||||
|
|
||||||
[self.statusView popUpStatusItemMenu:self.statusView.menu];
|
[[self.statusItem button] performClick:sender];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (IBAction)showPasswordWindow:(id)sender {
|
- (IBAction)showPasswordWindow:(id)sender {
|
||||||
@@ -546,15 +544,6 @@ static OSStatus MPHotKeyHander(EventHandlerCallRef nextHandler, EventRef theEven
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!self.key) {
|
|
||||||
NSAlert *alert = [NSAlert new];
|
|
||||||
alert.messageText = @"User Locked";
|
|
||||||
alert.informativeText = @"To export your sites, first unlock your user by opening Master Password.";
|
|
||||||
[alert runModal];
|
|
||||||
[self showPopup:nil];
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
NSDateFormatter *exportDateFormatter = [NSDateFormatter new];
|
NSDateFormatter *exportDateFormatter = [NSDateFormatter new];
|
||||||
[exportDateFormatter setDateFormat:@"yyyy'-'MM'-'dd"];
|
[exportDateFormatter setDateFormat:@"yyyy'-'MM'-'dd"];
|
||||||
|
|
||||||
@@ -579,11 +568,13 @@ static OSStatus MPHotKeyHander(EventHandlerCallRef nextHandler, EventRef theEven
|
|||||||
if ([savePanel runModal] == NSFileHandlingPanelCancelButton)
|
if ([savePanel runModal] == NSFileHandlingPanelCancelButton)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
[self exportSitesRevealPasswords:revealPasswords
|
[MPMacAppDelegate managedObjectContextPerformBlock:^(NSManagedObjectContext *context) {
|
||||||
askExportPassword:^NSString *(NSString *userName) {
|
NSError *error = nil;
|
||||||
|
NSString *exportedUser = [self exportSitesFor:[self activeUserInContext:context] revealPasswords:revealPasswords askExportPassword:
|
||||||
|
^NSString *(NSString *userName) {
|
||||||
return PearlMainQueueAwait( ^id {
|
return PearlMainQueueAwait( ^id {
|
||||||
NSAlert *alert = [NSAlert new];
|
NSAlert *alert = [NSAlert new];
|
||||||
[alert addButtonWithTitle:@"Import"];
|
[alert addButtonWithTitle:@"Export"];
|
||||||
[alert addButtonWithTitle:@"Cancel"];
|
[alert addButtonWithTitle:@"Cancel"];
|
||||||
alert.messageText = strf( @"Master Password For\n%@", userName );
|
alert.messageText = strf( @"Master Password For\n%@", userName );
|
||||||
alert.informativeText = @"Enter the current master password for this user.";
|
alert.informativeText = @"Enter the current master password for this user.";
|
||||||
@@ -594,19 +585,20 @@ static OSStatus MPHotKeyHander(EventHandlerCallRef nextHandler, EventRef theEven
|
|||||||
else
|
else
|
||||||
return nil;
|
return nil;
|
||||||
} );
|
} );
|
||||||
} result:^(NSString *mpsites, NSError *error) {
|
} error:&error];
|
||||||
if (!mpsites || error) {
|
|
||||||
|
if (error)
|
||||||
PearlMainQueue( ^{
|
PearlMainQueue( ^{
|
||||||
[[NSAlert alertWithError:MPError( error, @"Failed to export mpsites." )] runModal];
|
[[NSAlert alertWithError:MPError( error, @"Failed to export mpsites." )] runModal];
|
||||||
} );
|
} );
|
||||||
|
if (!exportedUser)
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
|
|
||||||
NSError *coordinateError = nil;
|
NSError *coordinateError = nil;
|
||||||
[[[NSFileCoordinator alloc] initWithFilePresenter:nil]
|
[[[NSFileCoordinator alloc] initWithFilePresenter:nil]
|
||||||
coordinateWritingItemAtURL:savePanel.URL options:0 error:&coordinateError byAccessor:^(NSURL *newURL) {
|
coordinateWritingItemAtURL:savePanel.URL options:0 error:&coordinateError byAccessor:^(NSURL *newURL) {
|
||||||
NSError *writeError = nil;
|
NSError *writeError = nil;
|
||||||
if (![mpsites writeToURL:newURL atomically:NO encoding:NSUTF8StringEncoding error:&writeError])
|
if (![exportedUser writeToURL:newURL atomically:NO encoding:NSUTF8StringEncoding error:&writeError])
|
||||||
PearlMainQueue( ^{
|
PearlMainQueue( ^{
|
||||||
[[NSAlert alertWithError:MPError( writeError, @"Could not write to the export file." )] runModal];
|
[[NSAlert alertWithError:MPError( writeError, @"Could not write to the export file." )] runModal];
|
||||||
} );
|
} );
|
||||||
@@ -688,13 +680,6 @@ static OSStatus MPHotKeyHander(EventHandlerCallRef nextHandler, EventRef theEven
|
|||||||
[self updateMenuItems];
|
[self updateMenuItems];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)showMenu {
|
|
||||||
|
|
||||||
[self updateMenuItems];
|
|
||||||
|
|
||||||
[self.statusView popUpStatusItemMenu:self.statusView.menu];
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void)updateMenuItems {
|
- (void)updateMenuItems {
|
||||||
|
|
||||||
MPUserEntity *activeUser = [self activeUserForMainThread];
|
MPUserEntity *activeUser = [self activeUserForMainThread];
|
||||||
@@ -749,6 +734,13 @@ static OSStatus MPHotKeyHander(EventHandlerCallRef nextHandler, EventRef theEven
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#pragma mark - NSMenuDelegate
|
||||||
|
|
||||||
|
- (void)menuNeedsUpdate:(NSMenu *)menu {
|
||||||
|
|
||||||
|
[self updateMenuItems];
|
||||||
|
}
|
||||||
|
|
||||||
#pragma mark - PearlConfigDelegate
|
#pragma mark - PearlConfigDelegate
|
||||||
|
|
||||||
- (void)didUpdateConfigForKey:(SEL)configKey fromValue:(id)oldValue {
|
- (void)didUpdateConfigForKey:(SEL)configKey fromValue:(id)oldValue {
|
||||||
@@ -769,13 +761,9 @@ static OSStatus MPHotKeyHander(EventHandlerCallRef nextHandler, EventRef theEven
|
|||||||
|
|
||||||
// Send info
|
// Send info
|
||||||
NSArray *countlyFeatures = @[
|
NSArray *countlyFeatures = @[
|
||||||
CLYConsentEvents, CLYConsentUserDetails, CLYConsentCrashReporting, CLYConsentViewTracking, CLYConsentStarRating
|
CLYConsentSessions, CLYConsentEvents, CLYConsentUserDetails, CLYConsentCrashReporting, CLYConsentViewTracking, CLYConsentStarRating
|
||||||
];
|
];
|
||||||
if ([[MPConfig get].sendInfo boolValue] || ![[MPConfig get].sendInfoDecided boolValue])
|
if ([[MPMacConfig get].sendInfo boolValue] || ![[MPMacConfig get].sendInfoDecided boolValue]) {
|
||||||
[Countly.sharedInstance giveConsentForFeature:CLYConsentSessions];
|
|
||||||
else
|
|
||||||
[Countly.sharedInstance cancelConsentForFeature:CLYConsentSessions];
|
|
||||||
if ([[MPMacConfig get].sendInfo boolValue]) {
|
|
||||||
if ([PearlLogger get].printLevel > PearlLogLevelInfo)
|
if ([PearlLogger get].printLevel > PearlLogLevelInfo)
|
||||||
[PearlLogger get].printLevel = PearlLogLevelInfo;
|
[PearlLogger get].printLevel = PearlLogLevelInfo;
|
||||||
|
|
||||||
|
|||||||
@@ -45,7 +45,7 @@
|
|||||||
@property(nonatomic, readonly) BOOL stored;
|
@property(nonatomic, readonly) BOOL stored;
|
||||||
@property(nonatomic, readonly) BOOL transient;
|
@property(nonatomic, readonly) BOOL transient;
|
||||||
|
|
||||||
- (instancetype)initWithEntity:(MPSiteEntity *)entity fuzzyGroups:(NSArray *)fuzzyGroups;
|
- (instancetype)initWithEntity:(MPSiteEntity *)entity queryGroups:(NSArray *)queryGroups;
|
||||||
- (instancetype)initWithName:(NSString *)siteName forUser:(MPUserEntity *)user;
|
- (instancetype)initWithName:(NSString *)siteName forUser:(MPUserEntity *)user;
|
||||||
- (MPSiteEntity *)entityInContext:(NSManagedObjectContext *)moc;
|
- (MPSiteEntity *)entityInContext:(NSManagedObjectContext *)moc;
|
||||||
|
|
||||||
|
|||||||
@@ -31,12 +31,12 @@
|
|||||||
|
|
||||||
@implementation MPSiteModel
|
@implementation MPSiteModel
|
||||||
|
|
||||||
- (instancetype)initWithEntity:(MPSiteEntity *)entity fuzzyGroups:(NSArray *)fuzzyGroups {
|
- (instancetype)initWithEntity:(MPSiteEntity *)entity queryGroups:(NSArray *)queryGroups {
|
||||||
|
|
||||||
if (!(self = [super init]))
|
if (!(self = [super init]))
|
||||||
return nil;
|
return nil;
|
||||||
|
|
||||||
[self setEntity:entity fuzzyGroups:fuzzyGroups];
|
[self setEntity:entity queryGroups:queryGroups];
|
||||||
self.initialized = YES;
|
self.initialized = YES;
|
||||||
|
|
||||||
return self;
|
return self;
|
||||||
@@ -53,23 +53,25 @@
|
|||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)setEntity:(MPSiteEntity *)entity fuzzyGroups:(NSArray *)fuzzyGroups {
|
- (void)setEntity:(MPSiteEntity *)entity queryGroups:(NSArray *)queryGroups {
|
||||||
|
|
||||||
if ([self.entityOID isEqual:entity.permanentObjectID])
|
if ([self.entityOID isEqual:entity.permanentObjectID])
|
||||||
return;
|
return;
|
||||||
self.entityOID = entity.permanentObjectID;
|
self.entityOID = entity.permanentObjectID;
|
||||||
|
|
||||||
NSString *siteName = entity.name;
|
NSString *siteName = entity.name;
|
||||||
NSMutableAttributedString *attributedSiteName = [[NSMutableAttributedString alloc] initWithString:siteName];
|
NSMutableAttributedString *attributedSiteName = [[NSMutableAttributedString alloc] initWithString:siteName?: @""];
|
||||||
for (NSUInteger f = 0, s = (NSUInteger)-1; f < [fuzzyGroups count]; ++f) {
|
if ([attributedSiteName length])
|
||||||
s = [siteName rangeOfString:fuzzyGroups[f] options:NSDiacriticInsensitiveSearch | NSCaseInsensitiveSearch
|
for (NSUInteger f = 0, s = 0; f < [queryGroups count]; ++f, ++s) {
|
||||||
range:NSMakeRange( s + 1, [siteName length] - (s + 1) )].location;
|
s = [siteName rangeOfString:queryGroups[f] options:NSDiacriticInsensitiveSearch | NSCaseInsensitiveSearch
|
||||||
|
range:NSMakeRange( s, [siteName length] - s )].location;
|
||||||
if (s == NSNotFound)
|
if (s == NSNotFound)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
[attributedSiteName addAttribute:NSBackgroundColorAttributeName value:[NSColor alternateSelectedControlColor]
|
[attributedSiteName addAttribute:NSBackgroundColorAttributeName value:[NSColor alternateSelectedControlColor]
|
||||||
range:NSMakeRange( s, [fuzzyGroups[f] length] )];
|
range:NSMakeRange( s, [queryGroups[f] length] )];
|
||||||
}
|
}
|
||||||
|
|
||||||
NSMutableParagraphStyle *paragraphStyle = [NSMutableParagraphStyle new];
|
NSMutableParagraphStyle *paragraphStyle = [NSMutableParagraphStyle new];
|
||||||
paragraphStyle.alignment = NSCenterTextAlignment;
|
paragraphStyle.alignment = NSCenterTextAlignment;
|
||||||
[attributedSiteName addAttribute:NSParagraphStyleAttributeName value:paragraphStyle range:NSMakeRange( 0, [siteName length] )];
|
[attributedSiteName addAttribute:NSParagraphStyleAttributeName value:paragraphStyle range:NSMakeRange( 0, [siteName length] )];
|
||||||
@@ -179,7 +181,8 @@
|
|||||||
if (algorithmVersion == self.algorithm.version)
|
if (algorithmVersion == self.algorithm.version)
|
||||||
return;
|
return;
|
||||||
[self willChangeValueForKey:@"outdated"];
|
[self willChangeValueForKey:@"outdated"];
|
||||||
self.algorithm = MPAlgorithmForVersion( algorithmVersion )?: self.algorithm;
|
self.algorithm =
|
||||||
|
MPAlgorithmForVersion( MIN( MPAlgorithmVersionLast, MAX( MPAlgorithmVersionFirst, algorithmVersion ) ) )?: self.algorithm;
|
||||||
[self didChangeValueForKey:@"outdated"];
|
[self didChangeValueForKey:@"outdated"];
|
||||||
|
|
||||||
if (self.entityOID)
|
if (self.entityOID)
|
||||||
|
|||||||
@@ -18,6 +18,7 @@
|
|||||||
|
|
||||||
#import <QuartzCore/QuartzCore.h>
|
#import <QuartzCore/QuartzCore.h>
|
||||||
#import <Countly/Countly.h>
|
#import <Countly/Countly.h>
|
||||||
|
#import <UserNotifications/UserNotifications.h>
|
||||||
#import "MPSitesWindowController.h"
|
#import "MPSitesWindowController.h"
|
||||||
#import "MPMacAppDelegate.h"
|
#import "MPMacAppDelegate.h"
|
||||||
#import "MPAppDelegate_Store.h"
|
#import "MPAppDelegate_Store.h"
|
||||||
@@ -52,13 +53,10 @@
|
|||||||
|
|
||||||
if (![[MPMacConfig get].sendInfoDecided boolValue]) {
|
if (![[MPMacConfig get].sendInfoDecided boolValue]) {
|
||||||
NSAlert *alert = [NSAlert new];
|
NSAlert *alert = [NSAlert new];
|
||||||
alert.messageText = @"Welcome to Master Password!";
|
alert.messageText = @"Diagnostics";
|
||||||
alert.informativeText = @"We want you to have a top-notch experience.\n"
|
alert.informativeText = @"We look for bugs, sudden crashes, runtime issues & statistics.\n\n"
|
||||||
@"Using diagnostics, we ensure the application keeps working as designed for you.\n"
|
@"Diagnostics are scrubbed and personal details will never leave your device.";
|
||||||
@"\n"
|
[alert addButtonWithTitle:@"Engage"];
|
||||||
@"We look out for application bugs, runtime issues, sudden crashes & usage counters.\n"
|
|
||||||
@"Needless to say, diagnostics are always scrubbed and personal details will never leave your device.";
|
|
||||||
[alert addButtonWithTitle:@"Thanks!"];
|
|
||||||
[alert addButtonWithTitle:@"Disable"];
|
[alert addButtonWithTitle:@"Disable"];
|
||||||
[alert beginSheetModalForWindow:self.window completionHandler:^(NSModalResponse returnCode) {
|
[alert beginSheetModalForWindow:self.window completionHandler:^(NSModalResponse returnCode) {
|
||||||
[MPMacConfig get].sendInfo = @(returnCode != NSAlertSecondButtonReturn);
|
[MPMacConfig get].sendInfo = @(returnCode != NSAlertSecondButtonReturn);
|
||||||
@@ -99,7 +97,16 @@
|
|||||||
self.siteTable.superview.superview.layer.mask = self.siteGradient;
|
self.siteTable.superview.superview.layer.mask = self.siteGradient;
|
||||||
|
|
||||||
self.siteTable.controller = self;
|
self.siteTable.controller = self;
|
||||||
prof_finish( @"ui" );
|
prof_rewind( @"ui" );
|
||||||
|
|
||||||
|
if (@available( macOS 10.14, * )) {
|
||||||
|
[[UNUserNotificationCenter currentNotificationCenter]
|
||||||
|
requestAuthorizationWithOptions:UNAuthorizationOptionAlert completionHandler:^(BOOL granted, NSError *error) {
|
||||||
|
if (!granted)
|
||||||
|
err( @"Couldn't obtain notification authorization: %@", error );
|
||||||
|
}];
|
||||||
|
}
|
||||||
|
prof_finish( @"notifications" );
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)dealloc {
|
- (void)dealloc {
|
||||||
@@ -550,13 +557,19 @@
|
|||||||
[self copyContent:self.shiftPressed? selectedSite.loginName: selectedSite.content];
|
[self copyContent:self.shiftPressed? selectedSite.loginName: selectedSite.content];
|
||||||
[NSApp hide:nil];
|
[NSApp hide:nil];
|
||||||
|
|
||||||
NSUserNotification *notification = [NSUserNotification new];
|
if (@available( macOS 10.14, * )) {
|
||||||
notification.title = @"Password Copied";
|
UNMutableNotificationContent *notification = [UNMutableNotificationContent new];
|
||||||
|
notification.title = self.shiftPressed? @"Login Copied": @"Password Copied";
|
||||||
if (selectedSite.loginName.length)
|
if (selectedSite.loginName.length)
|
||||||
notification.subtitle = strf( @"%@ at %@", selectedSite.loginName, selectedSite.name );
|
notification.subtitle = strf( @"%@ at %@", selectedSite.loginName, selectedSite.name );
|
||||||
else
|
else
|
||||||
notification.subtitle = selectedSite.name;
|
notification.subtitle = selectedSite.name;
|
||||||
[[NSUserNotificationCenter defaultUserNotificationCenter] deliverNotification:notification];
|
[[UNUserNotificationCenter currentNotificationCenter] addNotificationRequest:
|
||||||
|
[UNNotificationRequest requestWithIdentifier:selectedSite.name content:notification trigger:nil]
|
||||||
|
withCompletionHandler:^(NSError *error) {
|
||||||
|
dbg( @"notification: %@, completed w/errror: %@", notification, error );
|
||||||
|
}];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)updateUser {
|
- (void)updateUser {
|
||||||
@@ -598,22 +611,20 @@
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
static NSRegularExpression *fuzzyRE;
|
|
||||||
static dispatch_once_t once = 0;
|
|
||||||
dispatch_once( &once, ^{
|
|
||||||
fuzzyRE = [NSRegularExpression regularExpressionWithPattern:@"(.)" options:0 error:nil];
|
|
||||||
} );
|
|
||||||
|
|
||||||
prof_new( @"updateSites" );
|
prof_new( @"updateSites" );
|
||||||
NSString *queryString = self.siteField.stringValue;
|
NSString *queryString = self.siteField.stringValue;
|
||||||
NSString *queryPattern = [[queryString stringByReplacingMatchesOfExpression:fuzzyRE withTemplate:@"*$1"] stringByAppendingString:@"*"];
|
NSMutableArray *queryGroups = [NSMutableArray new];
|
||||||
prof_rewind( @"queryPattern" );
|
NSMutableString *queryPattern = [NSMutableString new];
|
||||||
NSMutableArray *fuzzyGroups = [NSMutableArray new];
|
[queryString enumerateSubstringsInRange: NSMakeRange(0, [queryString length]) options: NSStringEnumerationByComposedCharacterSequences
|
||||||
[fuzzyRE enumerateMatchesInString:queryString options:0 range:NSMakeRange( 0, queryString.length )
|
usingBlock: ^(NSString *substring, NSRange substringRange, NSRange enclosingRange, BOOL *stop) {
|
||||||
usingBlock:^(NSTextCheckingResult *result, NSMatchingFlags flags, BOOL *stop) {
|
if (substringRange.location < 10) {
|
||||||
[fuzzyGroups addObject:[queryString substringWithRange:result.range]];
|
[queryGroups addObject:substring];
|
||||||
|
[queryPattern appendString:@"*"];
|
||||||
|
}
|
||||||
|
[queryPattern appendString:substring];
|
||||||
}];
|
}];
|
||||||
prof_rewind( @"fuzzyRE" );
|
[queryPattern appendString:@"*"];
|
||||||
|
prof_rewind( @"queryPattern" );
|
||||||
[MPMacAppDelegate managedObjectContextPerformBlock:^(NSManagedObjectContext *context) {
|
[MPMacAppDelegate managedObjectContextPerformBlock:^(NSManagedObjectContext *context) {
|
||||||
prof_rewind( @"moc" );
|
prof_rewind( @"moc" );
|
||||||
|
|
||||||
@@ -635,7 +646,7 @@
|
|||||||
BOOL exact = NO;
|
BOOL exact = NO;
|
||||||
NSMutableArray *newSites = [NSMutableArray arrayWithCapacity:[siteResults count]];
|
NSMutableArray *newSites = [NSMutableArray arrayWithCapacity:[siteResults count]];
|
||||||
for (MPSiteEntity *site in siteResults) {
|
for (MPSiteEntity *site in siteResults) {
|
||||||
[newSites addObject:[[MPSiteModel alloc] initWithEntity:site fuzzyGroups:fuzzyGroups]];
|
[newSites addObject:[[MPSiteModel alloc] initWithEntity:site queryGroups:queryGroups]];
|
||||||
exact |= [site.name isEqualToString:queryString];
|
exact |= [site.name isEqualToString:queryString];
|
||||||
}
|
}
|
||||||
prof_rewind( @"newSites: %u, exact: %d", (uint)[siteResults count], exact );
|
prof_rewind( @"newSites: %u, exact: %d", (uint)[siteResults count], exact );
|
||||||
|
|||||||
@@ -722,7 +722,7 @@ Use the arrows ⇅ to navigate the list or esc ⎋ to exit.</string>
|
|||||||
<shadow key="shadow">
|
<shadow key="shadow">
|
||||||
<color key="color" name="controlLightHighlightColor" catalog="System" colorSpace="catalog"/>
|
<color key="color" name="controlLightHighlightColor" catalog="System" colorSpace="catalog"/>
|
||||||
</shadow>
|
</shadow>
|
||||||
<stepperCell key="cell" continuous="YES" alignment="left" minValue="1" maxValue="1000" doubleValue="1" id="73y-03-zHt"/>
|
<stepperCell key="cell" continuous="YES" alignment="left" maxValue="4294967295" doubleValue="1" valueWraps="YES" id="73y-03-zHt"/>
|
||||||
<connections>
|
<connections>
|
||||||
<binding destination="mcS-ik-b0n" name="value" keyPath="selection.algorithmVersion" id="GyA-hK-6cD"/>
|
<binding destination="mcS-ik-b0n" name="value" keyPath="selection.algorithmVersion" id="GyA-hK-6cD"/>
|
||||||
</connections>
|
</connections>
|
||||||
@@ -776,7 +776,7 @@ Use the arrows ⇅ to navigate the list or esc ⎋ to exit.</string>
|
|||||||
<shadow key="shadow">
|
<shadow key="shadow">
|
||||||
<color key="color" name="controlLightHighlightColor" catalog="System" colorSpace="catalog"/>
|
<color key="color" name="controlLightHighlightColor" catalog="System" colorSpace="catalog"/>
|
||||||
</shadow>
|
</shadow>
|
||||||
<stepperCell key="cell" continuous="YES" alignment="left" minValue="1" maxValue="1000" doubleValue="1" id="ikF-n4-xiI"/>
|
<stepperCell key="cell" continuous="YES" alignment="left" minValue="1" maxValue="4294967295" doubleValue="1" valueWraps="YES" id="ikF-n4-xiI"/>
|
||||||
<connections>
|
<connections>
|
||||||
<binding destination="mcS-ik-b0n" name="value" keyPath="selection.counter" id="qmm-6z-boy"/>
|
<binding destination="mcS-ik-b0n" name="value" keyPath="selection.counter" id="qmm-6z-boy"/>
|
||||||
</connections>
|
</connections>
|
||||||
|
|||||||
@@ -31,7 +31,6 @@
|
|||||||
[super viewDidLoad];
|
[super viewDidLoad];
|
||||||
|
|
||||||
self.mode = MPCombinedModeUserSelection;
|
self.mode = MPCombinedModeUserSelection;
|
||||||
[self performSegueWithIdentifier:@"users" sender:self];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)viewWillAppear:(BOOL)animated {
|
- (void)viewWillAppear:(BOOL)animated {
|
||||||
|
|||||||
@@ -33,13 +33,6 @@
|
|||||||
self.dismissSegueByButton = [NSMutableDictionary dictionary];
|
self.dismissSegueByButton = [NSMutableDictionary dictionary];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)viewDidLoad {
|
|
||||||
|
|
||||||
[super viewDidLoad];
|
|
||||||
|
|
||||||
[self performSegueWithIdentifier:@"root" sender:self];
|
|
||||||
}
|
|
||||||
|
|
||||||
- (UIViewController *)childViewControllerForStatusBarStyle {
|
- (UIViewController *)childViewControllerForStatusBarStyle {
|
||||||
|
|
||||||
return [self.childViewControllers lastObject];
|
return [self.childViewControllers lastObject];
|
||||||
|
|||||||
@@ -1,23 +0,0 @@
|
|||||||
//==============================================================================
|
|
||||||
// This file is part of Master Password.
|
|
||||||
// Copyright (c) 2011-2017, Maarten Billemont.
|
|
||||||
//
|
|
||||||
// Master Password is free software: you can redistribute it and/or modify
|
|
||||||
// it under the terms of the GNU General Public License as published by
|
|
||||||
// the Free Software Foundation, either version 3 of the License, or
|
|
||||||
// (at your option) any later version.
|
|
||||||
//
|
|
||||||
// Master Password is distributed in the hope that it will be useful,
|
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
// GNU General Public License for more details.
|
|
||||||
//
|
|
||||||
// You can find a copy of the GNU General Public License in the
|
|
||||||
// LICENSE file. Alternatively, see <http://www.gnu.org/licenses/>.
|
|
||||||
//==============================================================================
|
|
||||||
|
|
||||||
#import <Foundation/Foundation.h>
|
|
||||||
|
|
||||||
@interface MPRootSegue : UIStoryboardSegue
|
|
||||||
|
|
||||||
@end
|
|
||||||
@@ -1,35 +0,0 @@
|
|||||||
//==============================================================================
|
|
||||||
// This file is part of Master Password.
|
|
||||||
// Copyright (c) 2011-2017, Maarten Billemont.
|
|
||||||
//
|
|
||||||
// Master Password is free software: you can redistribute it and/or modify
|
|
||||||
// it under the terms of the GNU General Public License as published by
|
|
||||||
// the Free Software Foundation, either version 3 of the License, or
|
|
||||||
// (at your option) any later version.
|
|
||||||
//
|
|
||||||
// Master Password is distributed in the hope that it will be useful,
|
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
// GNU General Public License for more details.
|
|
||||||
//
|
|
||||||
// You can find a copy of the GNU General Public License in the
|
|
||||||
// LICENSE file. Alternatively, see <http://www.gnu.org/licenses/>.
|
|
||||||
//==============================================================================
|
|
||||||
|
|
||||||
#import "MPRootSegue.h"
|
|
||||||
|
|
||||||
@implementation MPRootSegue
|
|
||||||
|
|
||||||
- (void)perform {
|
|
||||||
|
|
||||||
UIViewController *sourceViewController = self.sourceViewController;
|
|
||||||
UIViewController *destinationViewController = self.destinationViewController;
|
|
||||||
[sourceViewController addChildViewController:destinationViewController];
|
|
||||||
destinationViewController.view.frame = sourceViewController.view.bounds;
|
|
||||||
destinationViewController.view.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
|
|
||||||
[sourceViewController.view addSubview:destinationViewController.view];
|
|
||||||
[destinationViewController didMoveToParentViewController:sourceViewController];
|
|
||||||
[sourceViewController setNeedsStatusBarAppearanceUpdate];
|
|
||||||
}
|
|
||||||
|
|
||||||
@end
|
|
||||||
@@ -27,7 +27,7 @@ typedef NS_ENUM ( NSUInteger, MPSiteCellMode ) {
|
|||||||
|
|
||||||
@interface MPSiteCell : MPCell<UIScrollViewDelegate, UITextFieldDelegate>
|
@interface MPSiteCell : MPCell<UIScrollViewDelegate, UITextFieldDelegate>
|
||||||
|
|
||||||
@property(nonatomic) NSArray *fuzzyGroups;
|
@property(nonatomic) NSArray *queryGroups;
|
||||||
|
|
||||||
- (void)setSite:(MPSiteEntity *)site animated:(BOOL)animated;
|
- (void)setSite:(MPSiteEntity *)site animated:(BOOL)animated;
|
||||||
- (void)setTransientSite:(NSString *)siteName animated:(BOOL)animated;
|
- (void)setTransientSite:(NSString *)siteName animated:(BOOL)animated;
|
||||||
|
|||||||
@@ -135,7 +135,7 @@
|
|||||||
[super prepareForReuse];
|
[super prepareForReuse];
|
||||||
|
|
||||||
self.siteOID = nil;
|
self.siteOID = nil;
|
||||||
self.fuzzyGroups = nil;
|
self.queryGroups = nil;
|
||||||
self.transientSite = nil;
|
self.transientSite = nil;
|
||||||
self.mode = MPPasswordCellModePassword;
|
self.mode = MPPasswordCellModePassword;
|
||||||
[self updateAnimated:NO];
|
[self updateAnimated:NO];
|
||||||
@@ -150,11 +150,11 @@
|
|||||||
|
|
||||||
#pragma mark - State
|
#pragma mark - State
|
||||||
|
|
||||||
- (void)setFuzzyGroups:(NSArray *)fuzzyGroups {
|
- (void)setQueryGroups:(NSArray *)queryGroups {
|
||||||
|
|
||||||
if (self.fuzzyGroups == fuzzyGroups)
|
if (self.queryGroups == queryGroups)
|
||||||
return;
|
return;
|
||||||
_fuzzyGroups = fuzzyGroups;
|
_queryGroups = queryGroups;
|
||||||
|
|
||||||
[self updateSiteName:[self siteInContext:[MPiOSAppDelegate managedObjectContextForMainThreadIfReady]]];
|
[self updateSiteName:[self siteInContext:[MPiOSAppDelegate managedObjectContextForMainThreadIfReady]]];
|
||||||
}
|
}
|
||||||
@@ -263,6 +263,7 @@
|
|||||||
|
|
||||||
UIAlertController *controller = [UIAlertController alertControllerWithTitle:strf( @"Delete %@?", site.name ) message:nil
|
UIAlertController *controller = [UIAlertController alertControllerWithTitle:strf( @"Delete %@?", site.name ) message:nil
|
||||||
preferredStyle:UIAlertControllerStyleActionSheet];
|
preferredStyle:UIAlertControllerStyleActionSheet];
|
||||||
|
[controller.popoverPresentationController setSourceView:sender];
|
||||||
[controller addAction:[UIAlertAction actionWithTitle:@"Delete Site" style:UIAlertActionStyleDestructive
|
[controller addAction:[UIAlertAction actionWithTitle:@"Delete Site" style:UIAlertActionStyleDestructive
|
||||||
handler:^(UIAlertAction *_Nonnull action) {
|
handler:^(UIAlertAction *_Nonnull action) {
|
||||||
[MPiOSAppDelegate managedObjectContextPerformBlock:^(NSManagedObjectContext *context) {
|
[MPiOSAppDelegate managedObjectContextPerformBlock:^(NSManagedObjectContext *context) {
|
||||||
@@ -284,6 +285,7 @@
|
|||||||
MPSiteEntity *mainSite = [self siteInContext:[MPiOSAppDelegate managedObjectContextForMainThreadIfReady]];
|
MPSiteEntity *mainSite = [self siteInContext:[MPiOSAppDelegate managedObjectContextForMainThreadIfReady]];
|
||||||
UIAlertController *controller = [UIAlertController alertControllerWithTitle:@"Change Password Type" message:nil
|
UIAlertController *controller = [UIAlertController alertControllerWithTitle:@"Change Password Type" message:nil
|
||||||
preferredStyle:UIAlertControllerStyleActionSheet];
|
preferredStyle:UIAlertControllerStyleActionSheet];
|
||||||
|
[controller.popoverPresentationController setSourceView:sender];
|
||||||
for (NSNumber *typeNumber in [mainSite.algorithm allTypes]) {
|
for (NSNumber *typeNumber in [mainSite.algorithm allTypes]) {
|
||||||
MPResultType type = (MPResultType)[typeNumber unsignedIntegerValue];
|
MPResultType type = (MPResultType)[typeNumber unsignedIntegerValue];
|
||||||
NSString *typeName = [mainSite.algorithm nameOfType:type];
|
NSString *typeName = [mainSite.algorithm nameOfType:type];
|
||||||
@@ -425,7 +427,7 @@
|
|||||||
if (!site || ![site isKindOfClass:[MPGeneratedSiteEntity class]])
|
if (!site || ![site isKindOfClass:[MPGeneratedSiteEntity class]])
|
||||||
return;
|
return;
|
||||||
|
|
||||||
((MPGeneratedSiteEntity *)site).counter = 1;
|
((MPGeneratedSiteEntity *)site).counter = MPCounterValueInitial;
|
||||||
[context saveToStore];
|
[context saveToStore];
|
||||||
|
|
||||||
[PearlOverlay showTemporaryOverlayWithTitle:@"Counter Reset" dismissAfter:2];
|
[PearlOverlay showTemporaryOverlayWithTitle:@"Counter Reset" dismissAfter:2];
|
||||||
@@ -444,6 +446,7 @@
|
|||||||
UIAlertController *controller = [UIAlertController alertControllerWithTitle:@"Create Site" message:
|
UIAlertController *controller = [UIAlertController alertControllerWithTitle:@"Create Site" message:
|
||||||
strf( @"Remember site named:\n%@", self.transientSite )
|
strf( @"Remember site named:\n%@", self.transientSite )
|
||||||
preferredStyle:UIAlertControllerStyleActionSheet];
|
preferredStyle:UIAlertControllerStyleActionSheet];
|
||||||
|
[controller.popoverPresentationController setSourceView:sender];
|
||||||
[controller addAction:[UIAlertAction actionWithTitle:@"Yes" style:UIAlertActionStyleDefault handler:
|
[controller addAction:[UIAlertAction actionWithTitle:@"Yes" style:UIAlertActionStyleDefault handler:
|
||||||
^(UIAlertAction *_Nonnull action) {
|
^(UIAlertAction *_Nonnull action) {
|
||||||
[[MPiOSAppDelegate get]
|
[[MPiOSAppDelegate get]
|
||||||
@@ -653,14 +656,14 @@
|
|||||||
NSString *siteName = self.transientSite?: site.name;
|
NSString *siteName = self.transientSite?: site.name;
|
||||||
NSMutableAttributedString *attributedSiteName = [[NSMutableAttributedString alloc] initWithString:siteName?: @""];
|
NSMutableAttributedString *attributedSiteName = [[NSMutableAttributedString alloc] initWithString:siteName?: @""];
|
||||||
if ([attributedSiteName length])
|
if ([attributedSiteName length])
|
||||||
for (NSUInteger f = 0, s = (NSUInteger)-1; f < [self.fuzzyGroups count]; ++f) {
|
for (NSUInteger f = 0, s = 0; f < [self.queryGroups count]; ++f, ++s) {
|
||||||
s = [siteName rangeOfString:self.fuzzyGroups[f] options:NSDiacriticInsensitiveSearch | NSCaseInsensitiveSearch
|
s = [siteName rangeOfString:self.queryGroups[f] options:NSDiacriticInsensitiveSearch | NSCaseInsensitiveSearch
|
||||||
range:NSMakeRange( s + 1, [siteName length] - (s + 1) )].location;
|
range:NSMakeRange( s, [siteName length] - s )].location;
|
||||||
if (s == NSNotFound)
|
if (s == NSNotFound)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
[attributedSiteName addAttribute:NSBackgroundColorAttributeName value:[UIColor redColor]
|
[attributedSiteName addAttribute:NSBackgroundColorAttributeName value:[UIColor redColor]
|
||||||
range:NSMakeRange( s, [self.fuzzyGroups[f] length] )];
|
range:NSMakeRange( s, [self.queryGroups[f] length] )];
|
||||||
}
|
}
|
||||||
|
|
||||||
if (self.transientSite)
|
if (self.transientSite)
|
||||||
|
|||||||
@@ -43,7 +43,7 @@
|
|||||||
UIView *sitesView = sitesVC.view;
|
UIView *sitesView = sitesVC.view;
|
||||||
sitesView.frame = combinedVC.view.bounds;
|
sitesView.frame = combinedVC.view.bounds;
|
||||||
sitesView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
|
sitesView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
|
||||||
[combinedVC.view insertSubview:sitesView belowSubview:combinedVC.usersVC.view];
|
[combinedVC.view insertSubview:sitesView belowSubview:combinedVC.usersVC.view.superview];
|
||||||
|
|
||||||
[sitesVC setActive:YES animated:self.animated completion:^(BOOL finished) {
|
[sitesVC setActive:YES animated:self.animated completion:^(BOOL finished) {
|
||||||
if (!finished)
|
if (!finished)
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ typedef NS_OPTIONS( NSUInteger, MPPasswordsTips ) {
|
|||||||
@interface MPSitesViewController()<NSFetchedResultsControllerDelegate>
|
@interface MPSitesViewController()<NSFetchedResultsControllerDelegate>
|
||||||
|
|
||||||
@property(nonatomic, strong) NSFetchedResultsController *fetchedResultsController;
|
@property(nonatomic, strong) NSFetchedResultsController *fetchedResultsController;
|
||||||
@property(nonatomic, strong) NSArray *fuzzyGroups;
|
@property(nonatomic, strong) NSArray *queryGroups;
|
||||||
@property(nonatomic, strong) NSCharacterSet *siteNameAcceptableCharactersSet;
|
@property(nonatomic, strong) NSCharacterSet *siteNameAcceptableCharactersSet;
|
||||||
@property(nonatomic, strong) NSMutableArray<NSMutableArray *> *dataSource;
|
@property(nonatomic, strong) NSMutableArray<NSMutableArray *> *dataSource;
|
||||||
@property(nonatomic, weak) UIViewController *popdownVC;
|
@property(nonatomic, weak) UIViewController *popdownVC;
|
||||||
@@ -120,12 +120,14 @@ typedef NS_OPTIONS( NSUInteger, MPPasswordsTips ) {
|
|||||||
PearlRemoveNotificationObservers();
|
PearlRemoveNotificationObservers();
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)viewWillLayoutSubviews {
|
- (void)viewDidLayoutSubviews {
|
||||||
|
|
||||||
self.collectionView.contentInset = [self.collectionView occludedInsets];
|
[super viewDidLayoutSubviews];
|
||||||
self.collectionView.scrollIndicatorInsets = self.collectionView.contentInset;
|
|
||||||
|
|
||||||
[super viewWillLayoutSubviews];
|
if (@available( iOS 11, * )) {
|
||||||
|
self.collectionView.layoutMargins =
|
||||||
|
UIEdgeInsetsMake( [self.collectionView occludedInsets].top - self.view.safeAreaInsets.top, 0, 0, 0 );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
|
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
|
||||||
@@ -160,7 +162,7 @@ typedef NS_OPTIONS( NSUInteger, MPPasswordsTips ) {
|
|||||||
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
|
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
|
||||||
|
|
||||||
MPSiteCell *cell = [MPSiteCell dequeueFromCollectionView:collectionView indexPath:indexPath];
|
MPSiteCell *cell = [MPSiteCell dequeueFromCollectionView:collectionView indexPath:indexPath];
|
||||||
[cell setFuzzyGroups:self.fuzzyGroups];
|
[cell setQueryGroups:self.queryGroups];
|
||||||
id item = self.dataSource[(NSUInteger)indexPath.section][(NSUInteger)indexPath.item];
|
id item = self.dataSource[(NSUInteger)indexPath.section][(NSUInteger)indexPath.item];
|
||||||
if ([item isKindOfClass:[MPSiteEntity class]])
|
if ([item isKindOfClass:[MPSiteEntity class]])
|
||||||
[cell setSite:item animated:NO];
|
[cell setSite:item animated:NO];
|
||||||
@@ -170,6 +172,19 @@ typedef NS_OPTIONS( NSUInteger, MPPasswordsTips ) {
|
|||||||
return cell;
|
return cell;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#pragma mark - UICollectionViewDelegateFlowLayout
|
||||||
|
|
||||||
|
- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout
|
||||||
|
sizeForItemAtIndexPath:(NSIndexPath *)indexPath {
|
||||||
|
|
||||||
|
UICollectionViewFlowLayout *layout = (UICollectionViewFlowLayout *)collectionViewLayout;
|
||||||
|
CGFloat availableWidth = collectionView.bounds.size.width
|
||||||
|
- collectionView.layoutMargins.left - collectionView.layoutMargins.right
|
||||||
|
- layout.sectionInset.left - layout.sectionInset.right;
|
||||||
|
CGFloat cells = MAX( 1, (int)((availableWidth + layout.minimumInteritemSpacing) / (318 + layout.minimumInteritemSpacing)) );
|
||||||
|
return CGSizeMake( (availableWidth - layout.minimumInteritemSpacing * (cells - 1)) / cells, 100 );
|
||||||
|
}
|
||||||
|
|
||||||
#pragma mark - UIScrollDelegate
|
#pragma mark - UIScrollDelegate
|
||||||
|
|
||||||
- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView {
|
- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView {
|
||||||
@@ -353,21 +368,19 @@ typedef NS_OPTIONS( NSUInteger, MPPasswordsTips ) {
|
|||||||
- (void)reloadSites {
|
- (void)reloadSites {
|
||||||
|
|
||||||
[self.fetchedResultsController.managedObjectContext performBlock:^{
|
[self.fetchedResultsController.managedObjectContext performBlock:^{
|
||||||
static NSRegularExpression *fuzzyRE;
|
|
||||||
static dispatch_once_t once = 0;
|
|
||||||
dispatch_once( &once, ^{
|
|
||||||
fuzzyRE = [NSRegularExpression regularExpressionWithPattern:@"(.)" options:0 error:nil];
|
|
||||||
} );
|
|
||||||
|
|
||||||
NSString *queryString = self.query;
|
NSString *queryString = self.query;
|
||||||
NSString *queryPattern = [[queryString stringByReplacingMatchesOfExpression:fuzzyRE withTemplate:@"*$1"]
|
NSMutableArray *queryGroups = [NSMutableArray new];
|
||||||
stringByAppendingString:@"*"];
|
NSMutableString *queryPattern = [NSMutableString new];
|
||||||
NSMutableArray *fuzzyGroups = [NSMutableArray new];
|
[queryString enumerateSubstringsInRange: NSMakeRange(0, [queryString length]) options: NSStringEnumerationByComposedCharacterSequences
|
||||||
[fuzzyRE enumerateMatchesInString:queryString options:0 range:NSMakeRange( 0, queryString.length )
|
usingBlock: ^(NSString *substring, NSRange substringRange, NSRange enclosingRange, BOOL *stop) {
|
||||||
usingBlock:^(NSTextCheckingResult *result, NSMatchingFlags flags, BOOL *stop) {
|
if (substringRange.location < 10) {
|
||||||
[fuzzyGroups addObject:[queryString substringWithRange:result.range]];
|
[queryGroups addObject:substring];
|
||||||
|
[queryPattern appendString:@"*"];
|
||||||
|
}
|
||||||
|
[queryPattern appendString:substring];
|
||||||
}];
|
}];
|
||||||
self.fuzzyGroups = fuzzyGroups;
|
[queryPattern appendString:@"*"];
|
||||||
|
self.queryGroups = queryGroups;
|
||||||
|
|
||||||
NSError *error = nil;
|
NSError *error = nil;
|
||||||
self.fetchedResultsController.fetchRequest.predicate =
|
self.fetchedResultsController.fetchRequest.predicate =
|
||||||
@@ -380,7 +393,7 @@ typedef NS_OPTIONS( NSUInteger, MPPasswordsTips ) {
|
|||||||
toSections:[self createDataSource]
|
toSections:[self createDataSource]
|
||||||
reloadItems:@[ MPTransientPasswordItem ] completion:^(BOOL finished) {
|
reloadItems:@[ MPTransientPasswordItem ] completion:^(BOOL finished) {
|
||||||
for (MPSiteCell *cell in self.collectionView.visibleCells)
|
for (MPSiteCell *cell in self.collectionView.visibleCells)
|
||||||
[cell setFuzzyGroups:self.fuzzyGroups];
|
[cell setQueryGroups:self.queryGroups];
|
||||||
}];
|
}];
|
||||||
} );
|
} );
|
||||||
}];
|
}];
|
||||||
|
|||||||
@@ -432,6 +432,7 @@ referenceSizeForFooterInSection:(NSInteger)section {
|
|||||||
|
|
||||||
NSManagedObjectID *userID = user.permanentObjectID;
|
NSManagedObjectID *userID = user.permanentObjectID;
|
||||||
UIAlertController *controller = [UIAlertController alertControllerWithTitle:user.name message:nil preferredStyle:UIAlertControllerStyleActionSheet];
|
UIAlertController *controller = [UIAlertController alertControllerWithTitle:user.name message:nil preferredStyle:UIAlertControllerStyleActionSheet];
|
||||||
|
[controller.popoverPresentationController setSourceView:avatarCell];
|
||||||
[controller addAction:[UIAlertAction actionWithTitle:@"Delete User" style:UIAlertActionStyleDestructive handler:^(UIAlertAction * _Nonnull action) {
|
[controller addAction:[UIAlertAction actionWithTitle:@"Delete User" style:UIAlertActionStyleDestructive handler:^(UIAlertAction * _Nonnull action) {
|
||||||
UIAlertController *controller_ = [UIAlertController alertControllerWithTitle:@"Deleting User" message:
|
UIAlertController *controller_ = [UIAlertController alertControllerWithTitle:@"Deleting User" message:
|
||||||
@"The user and its sites will be deleted." preferredStyle:UIAlertControllerStyleAlert];
|
@"The user and its sites will be deleted." preferredStyle:UIAlertControllerStyleAlert];
|
||||||
|
|||||||
@@ -100,9 +100,10 @@ decisionHandler:(void ( ^ )(WKNavigationActionPolicy))decisionHandler {
|
|||||||
|
|
||||||
- (IBAction)action:(id)sender {
|
- (IBAction)action:(id)sender {
|
||||||
|
|
||||||
UIAlertController *controller = [UIAlertController new];
|
UIAlertController *controller = [UIAlertController alertControllerWithTitle:self.webView.URL.host
|
||||||
controller.title = self.webView.URL.host;
|
message:self.webView.URL.absoluteString
|
||||||
controller.message = self.webView.URL.absoluteString;
|
preferredStyle:UIAlertControllerStyleActionSheet];
|
||||||
|
[controller.popoverPresentationController setSourceView:sender];
|
||||||
[controller addAction:[UIAlertAction actionWithTitle:@"Safari" style:UIAlertActionStyleDefault handler:^(UIAlertAction *action) {
|
[controller addAction:[UIAlertAction actionWithTitle:@"Safari" style:UIAlertActionStyleDefault handler:^(UIAlertAction *action) {
|
||||||
[UIApp openURL:self.webView.URL];
|
[UIApp openURL:self.webView.URL];
|
||||||
}]];
|
}]];
|
||||||
|
|||||||
@@ -23,6 +23,7 @@
|
|||||||
|
|
||||||
@interface MPiOSAppDelegate : MPAppDelegate_Shared <SKStoreProductViewControllerDelegate>
|
@interface MPiOSAppDelegate : MPAppDelegate_Shared <SKStoreProductViewControllerDelegate>
|
||||||
|
|
||||||
|
@property(nonatomic, strong) UIWindow *window;
|
||||||
@property(nonatomic, strong) SKStoreProductViewController *voltoViewController;
|
@property(nonatomic, strong) SKStoreProductViewController *voltoViewController;
|
||||||
|
|
||||||
- (void)openURL:(NSURL *)url;
|
- (void)openURL:(NSURL *)url;
|
||||||
|
|||||||
@@ -35,7 +35,7 @@
|
|||||||
@implementation CountlyPushNotifications(MPNotifications)
|
@implementation CountlyPushNotifications(MPNotifications)
|
||||||
|
|
||||||
- (void)openURL:(NSString *)URLString {
|
- (void)openURL:(NSString *)URLString {
|
||||||
[[MPiOSAppDelegate get].navigationController performSegueWithIdentifier:@"web" sender:[NSURL URLWithString:URLString]];
|
[[MPiOSAppDelegate get].window.rootViewController performSegueWithIdentifier:@"web" sender:[NSURL URLWithString:URLString]];
|
||||||
}
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
@@ -48,6 +48,8 @@
|
|||||||
|
|
||||||
@implementation MPiOSAppDelegate
|
@implementation MPiOSAppDelegate
|
||||||
|
|
||||||
|
@synthesize window;
|
||||||
|
|
||||||
+ (void)initialize {
|
+ (void)initialize {
|
||||||
|
|
||||||
[MPiOSConfig get];
|
[MPiOSConfig get];
|
||||||
@@ -57,7 +59,7 @@
|
|||||||
|
|
||||||
@try {
|
@try {
|
||||||
// Sentry
|
// Sentry
|
||||||
[SentrySDK initWithOptions:@{
|
[SentrySDK startWithOptions:@{
|
||||||
@"dsn" : NilToNSNull( decrypt( sentryDSN ) ),
|
@"dsn" : NilToNSNull( decrypt( sentryDSN ) ),
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
@"debug" : @(YES),
|
@"debug" : @(YES),
|
||||||
@@ -69,7 +71,7 @@
|
|||||||
@"debug" : @(NO),
|
@"debug" : @(NO),
|
||||||
@"environment" : @"Private",
|
@"environment" : @"Private",
|
||||||
#endif
|
#endif
|
||||||
@"enabled" : [MPiOSConfig get].sendInfo,
|
@"enabled" : @([[MPiOSConfig get].sendInfo boolValue] || ![[MPiOSConfig get].sendInfoDecided boolValue]),
|
||||||
@"enableAutoSessionTracking": @(YES),
|
@"enableAutoSessionTracking": @(YES),
|
||||||
}];
|
}];
|
||||||
[[PearlLogger get] registerListener:^BOOL(PearlLogMessage *message) {
|
[[PearlLogger get] registerListener:^BOOL(PearlLogMessage *message) {
|
||||||
@@ -150,12 +152,6 @@
|
|||||||
@catch (id exception) {
|
@catch (id exception) {
|
||||||
err( @"During Config Test: %@", exception );
|
err( @"During Config Test: %@", exception );
|
||||||
}
|
}
|
||||||
@try {
|
|
||||||
[super application:application didFinishLaunchingWithOptions:launchOptions];
|
|
||||||
}
|
|
||||||
@catch (id exception) {
|
|
||||||
err( @"During Pearl Application Launch: %@", exception );
|
|
||||||
}
|
|
||||||
@try {
|
@try {
|
||||||
inf( @"Started up with device identifier: %@", [PearlKeyChain deviceIdentifier] );
|
inf( @"Started up with device identifier: %@", [PearlKeyChain deviceIdentifier] );
|
||||||
|
|
||||||
@@ -190,8 +186,8 @@
|
|||||||
[migrateVC loadProductWithParameters:@{
|
[migrateVC loadProductWithParameters:@{
|
||||||
SKStoreProductParameterCampaignToken : @"app-masterpassword.ios", /* Campaign: From MasterPassword iOS */
|
SKStoreProductParameterCampaignToken : @"app-masterpassword.ios", /* Campaign: From MasterPassword iOS */
|
||||||
SKStoreProductParameterProviderToken : @153897, /* Provider: Maarten Billemont */
|
SKStoreProductParameterProviderToken : @153897, /* Provider: Maarten Billemont */
|
||||||
SKStoreProductParameterITunesItemIdentifier: @510296984, /* Application: MasterPassword iOS */
|
// SKStoreProductParameterITunesItemIdentifier: @510296984, /* Application: MasterPassword iOS */
|
||||||
//SKStoreProductParameterITunesItemIdentifier: @1500430196, /* Application: Volto iOS */
|
SKStoreProductParameterITunesItemIdentifier: @1500430196, /* Application: Volto iOS */
|
||||||
} completionBlock:^(BOOL result, NSError *error) {
|
} completionBlock:^(BOOL result, NSError *error) {
|
||||||
if (error)
|
if (error)
|
||||||
err( @"Failed loading Volto product information: %@", error );
|
err( @"Failed loading Volto product information: %@", error );
|
||||||
@@ -205,9 +201,8 @@
|
|||||||
}];
|
}];
|
||||||
|
|
||||||
PearlMainQueueOperation( ^{
|
PearlMainQueueOperation( ^{
|
||||||
[self.navigationController performSegueWithIdentifier:@"web" sender:[NSURL URLWithString:@"masterpassword://foo?bar=quux"]];
|
|
||||||
if ([[MPiOSConfig get].showSetup boolValue])
|
if ([[MPiOSConfig get].showSetup boolValue])
|
||||||
[self.navigationController performSegueWithIdentifier:@"setup" sender:self];
|
[self.window.rootViewController performSegueWithIdentifier:@"setup" sender:self];
|
||||||
|
|
||||||
[self consentFeatures];
|
[self consentFeatures];
|
||||||
} );
|
} );
|
||||||
@@ -245,7 +240,7 @@
|
|||||||
(id)[error localizedDescription]?: error )
|
(id)[error localizedDescription]?: error )
|
||||||
preferredStyle:UIAlertControllerStyleAlert];
|
preferredStyle:UIAlertControllerStyleAlert];
|
||||||
[alert addAction:[UIAlertAction actionWithTitle:@"Continue" style:UIAlertActionStyleCancel handler:nil]];
|
[alert addAction:[UIAlertAction actionWithTitle:@"Continue" style:UIAlertActionStyleCancel handler:nil]];
|
||||||
[self.navigationController presentViewController:alert animated:YES completion:nil];
|
[self.window.rootViewController presentViewController:alert animated:YES completion:nil];
|
||||||
} );
|
} );
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -257,7 +252,7 @@
|
|||||||
@"Master Password couldn't understand the import file."
|
@"Master Password couldn't understand the import file."
|
||||||
preferredStyle:UIAlertControllerStyleAlert];
|
preferredStyle:UIAlertControllerStyleAlert];
|
||||||
[alert addAction:[UIAlertAction actionWithTitle:@"Continue" style:UIAlertActionStyleCancel handler:nil]];
|
[alert addAction:[UIAlertAction actionWithTitle:@"Continue" style:UIAlertActionStyleCancel handler:nil]];
|
||||||
[self.navigationController presentViewController:alert animated:YES completion:nil];
|
[self.window.rootViewController presentViewController:alert animated:YES completion:nil];
|
||||||
} );
|
} );
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -297,8 +292,7 @@
|
|||||||
[self consentFeatures];
|
[self consentFeatures];
|
||||||
}]];
|
}]];
|
||||||
|
|
||||||
[(self.navigationController.presentedViewController?: (UIViewController *)self.navigationController)
|
[self.window.rootViewController presentViewController:alert animated:YES completion:nil];
|
||||||
presentViewController:alert animated:YES completion:nil];
|
|
||||||
} );
|
} );
|
||||||
|
|
||||||
return YES;
|
return YES;
|
||||||
@@ -343,8 +337,7 @@
|
|||||||
[MPiOSConfig get].notificationsDecided = @(YES);
|
[MPiOSConfig get].notificationsDecided = @(YES);
|
||||||
}
|
}
|
||||||
}]];
|
}]];
|
||||||
[(self.navigationController.presentedViewController?: (UIViewController *)self.navigationController)
|
[self.window.rootViewController presentViewController:alert animated:YES completion:nil];
|
||||||
presentViewController:alert animated:YES completion:nil];
|
|
||||||
} );
|
} );
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -373,7 +366,7 @@
|
|||||||
[alert addAction:[UIAlertAction actionWithTitle:@"Cancel" style:UIAlertActionStyleCancel handler:^(UIAlertAction *action) {
|
[alert addAction:[UIAlertAction actionWithTitle:@"Cancel" style:UIAlertActionStyleCancel handler:^(UIAlertAction *action) {
|
||||||
setResult( nil );
|
setResult( nil );
|
||||||
}]];
|
}]];
|
||||||
[self.navigationController presentViewController:alert animated:YES completion:nil];
|
[self.window.rootViewController presentViewController:alert animated:YES completion:nil];
|
||||||
} );
|
} );
|
||||||
} );
|
} );
|
||||||
} askUserPassword:^NSString *(NSString *userName) {
|
} askUserPassword:^NSString *(NSString *userName) {
|
||||||
@@ -391,7 +384,7 @@
|
|||||||
[alert addAction:[UIAlertAction actionWithTitle:@"Cancel" style:UIAlertActionStyleCancel handler:^(UIAlertAction *action) {
|
[alert addAction:[UIAlertAction actionWithTitle:@"Cancel" style:UIAlertActionStyleCancel handler:^(UIAlertAction *action) {
|
||||||
setResult( nil );
|
setResult( nil );
|
||||||
}]];
|
}]];
|
||||||
[self.navigationController presentViewController:alert animated:YES completion:nil];
|
[self.window.rootViewController presentViewController:alert animated:YES completion:nil];
|
||||||
} );
|
} );
|
||||||
} );
|
} );
|
||||||
} result:^(NSError *error) {
|
} result:^(NSError *error) {
|
||||||
@@ -402,7 +395,7 @@
|
|||||||
UIAlertController *controller = [UIAlertController alertControllerWithTitle:@"Error" message:[error localizedDescription]
|
UIAlertController *controller = [UIAlertController alertControllerWithTitle:@"Error" message:[error localizedDescription]
|
||||||
preferredStyle:UIAlertControllerStyleAlert];
|
preferredStyle:UIAlertControllerStyleAlert];
|
||||||
[controller addAction:[UIAlertAction actionWithTitle:@"Continue" style:UIAlertActionStyleCancel handler:nil]];
|
[controller addAction:[UIAlertAction actionWithTitle:@"Continue" style:UIAlertActionStyleCancel handler:nil]];
|
||||||
[self.navigationController presentViewController:controller animated:YES completion:nil];
|
[self.window.rootViewController presentViewController:controller animated:YES completion:nil];
|
||||||
}
|
}
|
||||||
} );
|
} );
|
||||||
}];
|
}];
|
||||||
@@ -412,8 +405,6 @@
|
|||||||
|
|
||||||
inf( @"Will foreground" );
|
inf( @"Will foreground" );
|
||||||
|
|
||||||
[super applicationWillEnterForeground:application];
|
|
||||||
|
|
||||||
[self.hangDetector start];
|
[self.hangDetector start];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -436,20 +427,16 @@
|
|||||||
[UIPasteboard generalPasteboard].string = @"";
|
[UIPasteboard generalPasteboard].string = @"";
|
||||||
}]];
|
}]];
|
||||||
[alert addAction:[UIAlertAction actionWithTitle:@"No" style:UIAlertActionStyleCancel handler:nil]];
|
[alert addAction:[UIAlertAction actionWithTitle:@"No" style:UIAlertActionStyleCancel handler:nil]];
|
||||||
[self.navigationController presentViewController:alert animated:YES completion:nil];
|
[self.window.rootViewController presentViewController:alert animated:YES completion:nil];
|
||||||
} );
|
} );
|
||||||
}
|
}
|
||||||
mpw_marshal_file_free( &importFile );
|
mpw_marshal_file_free( &importFile );
|
||||||
} );
|
} );
|
||||||
|
|
||||||
[super applicationDidBecomeActive:application];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)applicationDidReceiveMemoryWarning:(UIApplication *)application {
|
- (void)applicationDidReceiveMemoryWarning:(UIApplication *)application {
|
||||||
|
|
||||||
inf( @"Received memory warning." );
|
inf( @"Received memory warning." );
|
||||||
|
|
||||||
[super applicationDidReceiveMemoryWarning:application];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)applicationDidEnterBackground:(UIApplication *)application {
|
- (void)applicationDidEnterBackground:(UIApplication *)application {
|
||||||
@@ -462,8 +449,6 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
[self.hangDetector stop];
|
[self.hangDetector stop];
|
||||||
|
|
||||||
[super applicationDidEnterBackground:application];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#pragma mark - Behavior
|
#pragma mark - Behavior
|
||||||
@@ -480,7 +465,7 @@
|
|||||||
else if ([url.host isEqualToString:@"show-url"]) {
|
else if ([url.host isEqualToString:@"show-url"]) {
|
||||||
for (NSURLQueryItem *item in [NSURLComponents componentsWithString:[url absoluteString]].queryItems)
|
for (NSURLQueryItem *item in [NSURLComponents componentsWithString:[url absoluteString]].queryItems)
|
||||||
if ([item.name isEqualToString:@"url"]) {
|
if ([item.name isEqualToString:@"url"]) {
|
||||||
[[MPiOSAppDelegate get].navigationController performSegueWithIdentifier:@"web" sender:[NSURL URLWithString:item.value]];
|
[self.window.rootViewController performSegueWithIdentifier:@"web" sender:[NSURL URLWithString:item.value]];
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -513,7 +498,7 @@
|
|||||||
@"help@masterpassword.app"
|
@"help@masterpassword.app"
|
||||||
preferredStyle:UIAlertControllerStyleAlert];
|
preferredStyle:UIAlertControllerStyleAlert];
|
||||||
[alert addAction:[UIAlertAction actionWithTitle:@"Okay" style:UIAlertActionStyleCancel handler:nil]];
|
[alert addAction:[UIAlertAction actionWithTitle:@"Okay" style:UIAlertActionStyleCancel handler:nil]];
|
||||||
[self.navigationController presentViewController:alert animated:YES completion:nil];
|
[self.window.rootViewController presentViewController:alert animated:YES completion:nil];
|
||||||
}
|
}
|
||||||
else if (logs) {
|
else if (logs) {
|
||||||
UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"Feedback" message:
|
UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"Feedback" message:
|
||||||
@@ -527,7 +512,7 @@
|
|||||||
[alert addAction:[UIAlertAction actionWithTitle:@"No Logs" style:UIAlertActionStyleDefault handler:^(UIAlertAction *action) {
|
[alert addAction:[UIAlertAction actionWithTitle:@"No Logs" style:UIAlertActionStyleDefault handler:^(UIAlertAction *action) {
|
||||||
[self openFeedbackWithLogs:NO forVC:viewController];
|
[self openFeedbackWithLogs:NO forVC:viewController];
|
||||||
}]];
|
}]];
|
||||||
[self.navigationController presentViewController:alert animated:YES completion:nil];
|
[self.window.rootViewController presentViewController:alert animated:YES completion:nil];
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
[self openFeedbackWithLogs:NO forVC:viewController];
|
[self openFeedbackWithLogs:NO forVC:viewController];
|
||||||
@@ -573,15 +558,16 @@
|
|||||||
@"This may be due to corruption. You can either reset Master Password and "
|
@"This may be due to corruption. You can either reset Master Password and "
|
||||||
@"recreate your user, or E-Mail us your logs and leave your corrupt store as-is for now."
|
@"recreate your user, or E-Mail us your logs and leave your corrupt store as-is for now."
|
||||||
preferredStyle:UIAlertControllerStyleAlert];
|
preferredStyle:UIAlertControllerStyleAlert];
|
||||||
[alert addAction:[UIAlertAction actionWithTitle:@"E-Mail Logs" style:UIAlertActionStyleDefault
|
[alert addAction:[UIAlertAction actionWithTitle:@"Try Again" style:UIAlertActionStyleDefault handler:^(UIAlertAction *action) {
|
||||||
handler:^(UIAlertAction *action) {
|
[self retryCorruptStore];
|
||||||
|
}]];
|
||||||
|
[alert addAction:[UIAlertAction actionWithTitle:@"Send Logs" style:UIAlertActionStyleDefault handler:^(UIAlertAction *action) {
|
||||||
[self openFeedbackWithLogs:YES forVC:nil];
|
[self openFeedbackWithLogs:YES forVC:nil];
|
||||||
}]];
|
}]];
|
||||||
[alert addAction:[UIAlertAction actionWithTitle:@"Reset" style:UIAlertActionStyleDefault handler:^(UIAlertAction *action) {
|
[alert addAction:[UIAlertAction actionWithTitle:@"Reset" style:UIAlertActionStyleDefault handler:^(UIAlertAction *action) {
|
||||||
[self deleteAndResetStore];
|
[self deleteAndResetStore];
|
||||||
}]];
|
}]];
|
||||||
[alert addAction:[UIAlertAction actionWithTitle:@"Ignore" style:UIAlertActionStyleCancel handler:nil]];
|
[self.window.rootViewController presentViewController:alert animated:YES completion:nil];
|
||||||
[self.navigationController presentViewController:alert animated:YES completion:nil];
|
|
||||||
} );
|
} );
|
||||||
} );
|
} );
|
||||||
}
|
}
|
||||||
@@ -598,7 +584,7 @@
|
|||||||
@"Would you like to make all your passwords visible in the export file?\n\n"
|
@"Would you like to make all your passwords visible in the export file?\n\n"
|
||||||
@"A safe export will include all sites but make their passwords invisible.\n"
|
@"A safe export will include all sites but make their passwords invisible.\n"
|
||||||
@"It is great as a backup and remains safe when fallen in the wrong hands."
|
@"It is great as a backup and remains safe when fallen in the wrong hands."
|
||||||
preferredStyle:UIAlertControllerStyleActionSheet];
|
preferredStyle:UIAlertControllerStyleAlert];
|
||||||
[sheet addAction:[UIAlertAction actionWithTitle:@"Safe Export" style:UIAlertActionStyleDefault handler:^(UIAlertAction *action) {
|
[sheet addAction:[UIAlertAction actionWithTitle:@"Safe Export" style:UIAlertActionStyleDefault handler:^(UIAlertAction *action) {
|
||||||
[self showExportRevealPasswords:NO forVC:viewController];
|
[self showExportRevealPasswords:NO forVC:viewController];
|
||||||
}]];
|
}]];
|
||||||
@@ -606,10 +592,10 @@
|
|||||||
[self showExportRevealPasswords:YES forVC:viewController];
|
[self showExportRevealPasswords:YES forVC:viewController];
|
||||||
}]];
|
}]];
|
||||||
[sheet addAction:[UIAlertAction actionWithTitle:@"Cancel" style:UIAlertActionStyleCancel handler:nil]];
|
[sheet addAction:[UIAlertAction actionWithTitle:@"Cancel" style:UIAlertActionStyleCancel handler:nil]];
|
||||||
[self.navigationController presentViewController:sheet animated:YES completion:nil];
|
[self.window.rootViewController presentViewController:sheet animated:YES completion:nil];
|
||||||
}]];
|
}]];
|
||||||
[alert addAction:[UIAlertAction actionWithTitle:@"Cancel" style:UIAlertActionStyleCancel handler:nil]];
|
[alert addAction:[UIAlertAction actionWithTitle:@"Cancel" style:UIAlertActionStyleCancel handler:nil]];
|
||||||
[self.navigationController presentViewController:alert animated:YES completion:nil];
|
[self.window.rootViewController presentViewController:alert animated:YES completion:nil];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)showExportRevealPasswords:(BOOL)revealPasswords forVC:(UIViewController *)viewController {
|
- (void)showExportRevealPasswords:(BOOL)revealPasswords forVC:(UIViewController *)viewController {
|
||||||
@@ -620,41 +606,46 @@
|
|||||||
@"Close Master Password, go into Settings and add a Mail account."
|
@"Close Master Password, go into Settings and add a Mail account."
|
||||||
preferredStyle:UIAlertControllerStyleAlert];
|
preferredStyle:UIAlertControllerStyleAlert];
|
||||||
[alert addAction:[UIAlertAction actionWithTitle:@"Okay" style:UIAlertActionStyleCancel handler:nil]];
|
[alert addAction:[UIAlertAction actionWithTitle:@"Okay" style:UIAlertActionStyleCancel handler:nil]];
|
||||||
[self.navigationController presentViewController:alert animated:YES completion:nil];
|
[self.window.rootViewController presentViewController:alert animated:YES completion:nil];
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
[MPiOSAppDelegate managedObjectContextPerformBlock:^(NSManagedObjectContext *context) {
|
[MPiOSAppDelegate managedObjectContextPerformBlock:^(NSManagedObjectContext *context) {
|
||||||
NSError *error = nil;
|
NSError *error = nil;
|
||||||
NSString *exportedUser = [self exportSitesFor:[self activeUserInContext:context] revealPasswords:revealPasswords askExportPassword:^NSString *(NSString *userName) {
|
NSString *exportedUser = [self exportSitesFor:[self activeUserInContext:context] revealPasswords:revealPasswords askExportPassword:
|
||||||
|
^NSString *(NSString *userName) {
|
||||||
return PearlAwait( ^(void (^setResult)(id)) {
|
return PearlAwait( ^(void (^setResult)(id)) {
|
||||||
PearlMainQueue( ^{
|
PearlMainQueue( ^{
|
||||||
UIAlertController *alert = [UIAlertController alertControllerWithTitle:strf( @"Master Password For:\n%@", userName )
|
UIAlertController *alert = [UIAlertController alertControllerWithTitle:strf(
|
||||||
|
@"Master Password For:\n%@", userName )
|
||||||
message:@"Enter your master password to export the user."
|
message:@"Enter your master password to export the user."
|
||||||
preferredStyle:UIAlertControllerStyleAlert];
|
preferredStyle:UIAlertControllerStyleAlert];
|
||||||
[alert addTextFieldWithConfigurationHandler:^(UITextField *textField) {
|
[alert addTextFieldWithConfigurationHandler:^(UITextField *textField) {
|
||||||
textField.secureTextEntry = YES;
|
textField.secureTextEntry = YES;
|
||||||
}];
|
}];
|
||||||
[alert addAction:[UIAlertAction actionWithTitle:@"Export" style:UIAlertActionStyleDefault handler:^(UIAlertAction *action) {
|
[alert addAction:[UIAlertAction actionWithTitle:@"Export" style:UIAlertActionStyleDefault
|
||||||
|
handler:^(UIAlertAction *action) {
|
||||||
setResult( alert.textFields.firstObject.text );
|
setResult( alert.textFields.firstObject.text );
|
||||||
}]];
|
}]];
|
||||||
[alert addAction:[UIAlertAction actionWithTitle:@"Cancel" style:UIAlertActionStyleCancel handler:^(UIAlertAction *action) {
|
[alert addAction:[UIAlertAction actionWithTitle:@"Cancel" style:UIAlertActionStyleCancel
|
||||||
|
handler:^(UIAlertAction *action) {
|
||||||
setResult( nil );
|
setResult( nil );
|
||||||
}]];
|
}]];
|
||||||
[self.navigationController presentViewController:alert animated:YES completion:nil];
|
[self.window.rootViewController presentViewController:alert animated:YES completion:nil];
|
||||||
} );
|
} );
|
||||||
} );
|
} );
|
||||||
} error:&error];
|
} error:&error];
|
||||||
|
|
||||||
PearlMainQueue( ^{
|
PearlMainQueue( ^{
|
||||||
if (!exportedUser || error) {
|
if (error) {
|
||||||
MPError( error, @"Failed to export mpsites." );
|
MPError( error, @"Failed to export mpsites." );
|
||||||
UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"Export Error" message:[error localizedDescription]
|
UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"Export Error" message:[error localizedDescription]
|
||||||
preferredStyle:UIAlertControllerStyleAlert];
|
preferredStyle:UIAlertControllerStyleAlert];
|
||||||
[alert addAction:[UIAlertAction actionWithTitle:@"Okay" style:UIAlertActionStyleCancel handler:nil]];
|
[alert addAction:[UIAlertAction actionWithTitle:@"Okay" style:UIAlertActionStyleCancel handler:nil]];
|
||||||
[self.navigationController presentViewController:alert animated:YES completion:nil];
|
[self.window.rootViewController presentViewController:alert animated:YES completion:nil];
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
if (!exportedUser)
|
||||||
|
return;
|
||||||
|
|
||||||
NSDateFormatter *exportDateFormatter = [NSDateFormatter new];
|
NSDateFormatter *exportDateFormatter = [NSDateFormatter new];
|
||||||
[exportDateFormatter setDateFormat:@"yyyy'-'MM'-'dd"];
|
[exportDateFormatter setDateFormat:@"yyyy'-'MM'-'dd"];
|
||||||
@@ -662,7 +653,7 @@
|
|||||||
[self activeUserForMainThread].name, [exportDateFormatter stringFromDate:[NSDate date]] );
|
[self activeUserForMainThread].name, [exportDateFormatter stringFromDate:[NSDate date]] );
|
||||||
|
|
||||||
UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"Export Destination" message:nil
|
UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"Export Destination" message:nil
|
||||||
preferredStyle:UIAlertControllerStyleActionSheet];
|
preferredStyle:UIAlertControllerStyleAlert];
|
||||||
[alert addAction:[UIAlertAction actionWithTitle:@"Send As E-Mail" style:UIAlertActionStyleDefault handler:^(UIAlertAction *action) {
|
[alert addAction:[UIAlertAction actionWithTitle:@"Send As E-Mail" style:UIAlertActionStyleDefault handler:^(UIAlertAction *action) {
|
||||||
NSString *message;
|
NSString *message;
|
||||||
if (revealPasswords)
|
if (revealPasswords)
|
||||||
@@ -707,7 +698,7 @@
|
|||||||
}
|
}
|
||||||
}]];
|
}]];
|
||||||
[alert addAction:[UIAlertAction actionWithTitle:@"Continue" style:UIAlertActionStyleCancel handler:nil]];
|
[alert addAction:[UIAlertAction actionWithTitle:@"Continue" style:UIAlertActionStyleCancel handler:nil]];
|
||||||
[self.navigationController presentViewController:alert animated:YES completion:nil];
|
[self.window.rootViewController presentViewController:alert animated:YES completion:nil];
|
||||||
} );
|
} );
|
||||||
}];
|
}];
|
||||||
}
|
}
|
||||||
@@ -724,14 +715,14 @@
|
|||||||
|
|
||||||
UIAlertController *usersSheet = [UIAlertController alertControllerWithTitle:@"Migrate User"
|
UIAlertController *usersSheet = [UIAlertController alertControllerWithTitle:@"Migrate User"
|
||||||
message:@"Choose a user to migrate out to Volto."
|
message:@"Choose a user to migrate out to Volto."
|
||||||
preferredStyle:UIAlertControllerStyleActionSheet];
|
preferredStyle:UIAlertControllerStyleAlert];
|
||||||
[usersSheet addAction:[UIAlertAction actionWithTitle:@"Cancel" style:UIAlertActionStyleCancel handler:nil]];
|
[usersSheet addAction:[UIAlertAction actionWithTitle:@"Cancel" style:UIAlertActionStyleCancel handler:nil]];
|
||||||
for (MPUserEntity *user_ in users)
|
for (MPUserEntity *user_ in users)
|
||||||
[usersSheet addAction:[UIAlertAction actionWithTitle:user_.name style:UIAlertActionStyleDefault handler:
|
[usersSheet addAction:[UIAlertAction actionWithTitle:user_.name style:UIAlertActionStyleDefault handler:
|
||||||
^(UIAlertAction *action) { [self migrateFor:user_]; }]];
|
^(UIAlertAction *action) { [self migrateFor:user_]; }]];
|
||||||
|
|
||||||
PearlMainQueue( ^{
|
PearlMainQueue( ^{
|
||||||
[self.navigationController presentViewController:usersSheet animated:YES completion:nil];
|
[self.window.rootViewController presentViewController:usersSheet animated:YES completion:nil];
|
||||||
} );
|
} );
|
||||||
}];
|
}];
|
||||||
return;
|
return;
|
||||||
@@ -753,21 +744,22 @@
|
|||||||
^(UIAlertAction *action) { setResult( alert.textFields.firstObject.text ); }]];
|
^(UIAlertAction *action) { setResult( alert.textFields.firstObject.text ); }]];
|
||||||
[alert addAction:[UIAlertAction actionWithTitle:@"Cancel" style:UIAlertActionStyleCancel handler:
|
[alert addAction:[UIAlertAction actionWithTitle:@"Cancel" style:UIAlertActionStyleCancel handler:
|
||||||
^(UIAlertAction *action) { setResult( nil ); }]];
|
^(UIAlertAction *action) { setResult( nil ); }]];
|
||||||
[self.navigationController presentViewController:alert animated:YES completion:nil];
|
[self.window.rootViewController presentViewController:alert animated:YES completion:nil];
|
||||||
} );
|
} );
|
||||||
} );
|
} );
|
||||||
} error:&error];
|
} error:&error];
|
||||||
|
|
||||||
PearlMainQueue( ^{
|
PearlMainQueue( ^{
|
||||||
if (!exportedUser || error) {
|
if (error) {
|
||||||
MPError( error, @"Failed to export user." );
|
MPError( error, @"Failed to export user." );
|
||||||
UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"Export Error"
|
UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"Export Error"
|
||||||
message:[error localizedDescription]
|
message:[error localizedDescription]
|
||||||
preferredStyle:UIAlertControllerStyleAlert];
|
preferredStyle:UIAlertControllerStyleAlert];
|
||||||
[alert addAction:[UIAlertAction actionWithTitle:@"Okay" style:UIAlertActionStyleCancel handler:nil]];
|
[alert addAction:[UIAlertAction actionWithTitle:@"Okay" style:UIAlertActionStyleCancel handler:nil]];
|
||||||
[self.navigationController presentViewController:alert animated:YES completion:nil];
|
[self.window.rootViewController presentViewController:alert animated:YES completion:nil];
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
if (!exportedUser)
|
||||||
|
return;
|
||||||
|
|
||||||
NSURLComponents *components = [NSURLComponents new];
|
NSURLComponents *components = [NSURLComponents new];
|
||||||
components.scheme = @"volto";
|
components.scheme = @"volto";
|
||||||
@@ -779,7 +771,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
else if (self.voltoViewController)
|
else if (self.voltoViewController)
|
||||||
[self.navigationController presentViewController:self.voltoViewController animated:YES completion:nil];
|
[self.window.rootViewController presentViewController:self.voltoViewController animated:YES completion:nil];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)changeMasterPasswordFor:(MPUserEntity *)user saveInContext:(NSManagedObjectContext *)moc didResetBlock:(void ( ^ )(void))didReset {
|
- (void)changeMasterPasswordFor:(MPUserEntity *)user saveInContext:(NSManagedObjectContext *)moc didResetBlock:(void ( ^ )(void))didReset {
|
||||||
@@ -790,7 +782,7 @@
|
|||||||
@"Changing your master password will cause all your generated passwords to change!\n"
|
@"Changing your master password will cause all your generated passwords to change!\n"
|
||||||
@"Changing the master password back to the old one will cause your passwords to revert as well."
|
@"Changing the master password back to the old one will cause your passwords to revert as well."
|
||||||
preferredStyle:UIAlertControllerStyleAlert];
|
preferredStyle:UIAlertControllerStyleAlert];
|
||||||
[alert addAction:[UIAlertAction actionWithTitle:@"Abort" style:UIAlertActionStyleDefault handler:^(UIAlertAction *action) {
|
[alert addAction:[UIAlertAction actionWithTitle:@"Continue" style:UIAlertActionStyleDefault handler:^(UIAlertAction *action) {
|
||||||
[moc performBlockAndWait:^{
|
[moc performBlockAndWait:^{
|
||||||
inf( @"Clearing keyID for user: %@.", user.userID );
|
inf( @"Clearing keyID for user: %@.", user.userID );
|
||||||
user.keyID = nil;
|
user.keyID = nil;
|
||||||
@@ -803,7 +795,7 @@
|
|||||||
didReset();
|
didReset();
|
||||||
}]];
|
}]];
|
||||||
[alert addAction:[UIAlertAction actionWithTitle:@"Abort" style:UIAlertActionStyleCancel handler:nil]];
|
[alert addAction:[UIAlertAction actionWithTitle:@"Abort" style:UIAlertActionStyleCancel handler:nil]];
|
||||||
[self.navigationController presentViewController:alert animated:YES completion:nil];
|
[self.window.rootViewController presentViewController:alert animated:YES completion:nil];
|
||||||
} );
|
} );
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -835,20 +827,16 @@
|
|||||||
|
|
||||||
// Send info
|
// Send info
|
||||||
NSArray *countlyFeatures = @[
|
NSArray *countlyFeatures = @[
|
||||||
CLYConsentEvents, CLYConsentUserDetails, CLYConsentCrashReporting, CLYConsentViewTracking, CLYConsentStarRating
|
CLYConsentSessions, CLYConsentEvents, CLYConsentUserDetails, CLYConsentCrashReporting, CLYConsentViewTracking, CLYConsentStarRating
|
||||||
];
|
];
|
||||||
if ([[MPConfig get].sendInfo boolValue] || ![[MPConfig get].sendInfoDecided boolValue])
|
if ([[MPiOSConfig get].sendInfo boolValue] || ![[MPiOSConfig get].sendInfoDecided boolValue]) {
|
||||||
[Countly.sharedInstance giveConsentForFeature:CLYConsentSessions];
|
|
||||||
else
|
|
||||||
[Countly.sharedInstance cancelConsentForFeature:CLYConsentSessions];
|
|
||||||
if ([[MPConfig get].sendInfo boolValue]) {
|
|
||||||
if ([PearlLogger get].printLevel > PearlLogLevelInfo)
|
if ([PearlLogger get].printLevel > PearlLogLevelInfo)
|
||||||
[PearlLogger get].printLevel = PearlLogLevelInfo;
|
[PearlLogger get].printLevel = PearlLogLevelInfo;
|
||||||
|
|
||||||
[SentrySDK.currentHub getClient].options.enabled = @YES;
|
[SentrySDK.currentHub getClient].options.enabled = @YES;
|
||||||
[SentrySDK configureScope:^(SentryScope *scope) {
|
[SentrySDK configureScope:^(SentryScope *scope) {
|
||||||
[scope setExtraValue:[MPConfig get].rememberLogin forKey:@"rememberLogin"];
|
[scope setExtraValue:[MPiOSConfig get].rememberLogin forKey:@"rememberLogin"];
|
||||||
[scope setExtraValue:[MPConfig get].sendInfo forKey:@"sendInfo"];
|
[scope setExtraValue:[MPiOSConfig get].sendInfo forKey:@"sendInfo"];
|
||||||
[scope setExtraValue:[MPiOSConfig get].helpHidden forKey:@"helpHidden"];
|
[scope setExtraValue:[MPiOSConfig get].helpHidden forKey:@"helpHidden"];
|
||||||
[scope setExtraValue:[MPiOSConfig get].showSetup forKey:@"showQuickStart"];
|
[scope setExtraValue:[MPiOSConfig get].showSetup forKey:@"showQuickStart"];
|
||||||
[scope setExtraValue:[PearlConfig get].firstRun forKey:@"firstRun"];
|
[scope setExtraValue:[PearlConfig get].firstRun forKey:@"firstRun"];
|
||||||
@@ -865,9 +853,8 @@
|
|||||||
#else
|
#else
|
||||||
[scope setExtraValue:@(NO) forKey:@"reviewedVersion"];
|
[scope setExtraValue:@(NO) forKey:@"reviewedVersion"];
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
[Countly.sharedInstance giveConsentForFeatures:countlyFeatures];
|
|
||||||
}];
|
}];
|
||||||
|
[Countly.sharedInstance giveConsentForFeatures:countlyFeatures];
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
[Countly.sharedInstance cancelConsentForFeatures:countlyFeatures];
|
[Countly.sharedInstance cancelConsentForFeatures:countlyFeatures];
|
||||||
|
|||||||
@@ -33,8 +33,8 @@
|
|||||||
NSStringFromSelector( @selector( siteInfoHidden ) ) : @YES,
|
NSStringFromSelector( @selector( siteInfoHidden ) ) : @YES,
|
||||||
NSStringFromSelector( @selector( showSetup ) ) : @YES,
|
NSStringFromSelector( @selector( showSetup ) ) : @YES,
|
||||||
NSStringFromSelector( @selector( appleID ) ) : @"510296984",
|
NSStringFromSelector( @selector( appleID ) ) : @"510296984",
|
||||||
NSStringFromSelector( @selector( actionsTipShown ) ) : @(!self.firstRun),
|
NSStringFromSelector( @selector( actionsTipShown ) ) : @(![self.firstRun boolValue]),
|
||||||
NSStringFromSelector( @selector( typeTipShown ) ) : @(!self.firstRun),
|
NSStringFromSelector( @selector( typeTipShown ) ) : @(![self.firstRun boolValue]),
|
||||||
NSStringFromSelector( @selector( loginNameTipShown ) ): @NO,
|
NSStringFromSelector( @selector( loginNameTipShown ) ): @NO,
|
||||||
NSStringFromSelector( @selector( traceMode ) ) : @NO,
|
NSStringFromSelector( @selector( traceMode ) ) : @NO,
|
||||||
NSStringFromSelector( @selector( dictationSearch ) ) : @NO,
|
NSStringFromSelector( @selector( dictationSearch ) ) : @NO,
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="16096" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" colorMatched="YES" initialViewController="Q1S-vU-GGO">
|
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="16097" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" colorMatched="YES" initialViewController="Q1S-vU-GGO">
|
||||||
<device id="retina6_1" orientation="portrait" appearance="light"/>
|
<device id="retina6_1" orientation="portrait" appearance="light"/>
|
||||||
<dependencies>
|
<dependencies>
|
||||||
<deployment identifier="iOS"/>
|
<deployment identifier="iOS"/>
|
||||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="16086"/>
|
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="16087"/>
|
||||||
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
<customFonts key="customFonts">
|
<customFonts key="customFonts">
|
||||||
@@ -69,7 +69,7 @@
|
|||||||
</collectionViewFlowLayout>
|
</collectionViewFlowLayout>
|
||||||
<cells>
|
<cells>
|
||||||
<collectionViewCell opaque="NO" multipleTouchEnabled="YES" contentMode="center" reuseIdentifier="MPAvatarCell" id="Zab-uQ-uk9" customClass="MPAvatarCell">
|
<collectionViewCell opaque="NO" multipleTouchEnabled="YES" contentMode="center" reuseIdentifier="MPAvatarCell" id="Zab-uQ-uk9" customClass="MPAvatarCell">
|
||||||
<rect key="frame" x="80" y="114.5" width="215" height="667"/>
|
<rect key="frame" x="80" y="115" width="215" height="667"/>
|
||||||
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMaxX="YES" flexibleMinY="YES" flexibleMaxY="YES"/>
|
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMaxX="YES" flexibleMinY="YES" flexibleMaxY="YES"/>
|
||||||
<view key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center">
|
<view key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center">
|
||||||
<rect key="frame" x="0.0" y="0.0" width="215" height="667"/>
|
<rect key="frame" x="0.0" y="0.0" width="215" height="667"/>
|
||||||
@@ -97,10 +97,10 @@
|
|||||||
</constraints>
|
</constraints>
|
||||||
</imageView>
|
</imageView>
|
||||||
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="0Sa-Vg-EEI" userLabel="Name Backdrop">
|
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="0Sa-Vg-EEI" userLabel="Name Backdrop">
|
||||||
<rect key="frame" x="43.5" y="263" width="128.5" height="16"/>
|
<rect key="frame" x="43.5" y="263" width="128" height="16"/>
|
||||||
<subviews>
|
<subviews>
|
||||||
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" horizontalCompressionResistancePriority="1000" text="Maarten Billemont" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" minimumFontSize="10" adjustsLetterSpacingToFitWidth="YES" translatesAutoresizingMaskIntoConstraints="NO" id="cLT-s0-4SQ" userLabel="Name Field">
|
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" horizontalCompressionResistancePriority="1000" text="Maarten Billemont" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" minimumFontSize="10" adjustsLetterSpacingToFitWidth="YES" translatesAutoresizingMaskIntoConstraints="NO" id="cLT-s0-4SQ" userLabel="Name Field">
|
||||||
<rect key="frame" x="5" y="0.0" width="118.5" height="16"/>
|
<rect key="frame" x="5" y="0.0" width="118" height="16"/>
|
||||||
<fontDescription key="fontDescription" name="Exo2.0-ExtraBold" family="Exo 2.0" pointSize="13"/>
|
<fontDescription key="fontDescription" name="Exo2.0-ExtraBold" family="Exo 2.0" pointSize="13"/>
|
||||||
<color key="textColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
<color key="textColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||||
<nil key="highlightedColor"/>
|
<nil key="highlightedColor"/>
|
||||||
@@ -288,14 +288,14 @@
|
|||||||
</connections>
|
</connections>
|
||||||
</button>
|
</button>
|
||||||
<view userInteractionEnabled="NO" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="069-Pu-yXe" userLabel="Thanks Tip">
|
<view userInteractionEnabled="NO" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="069-Pu-yXe" userLabel="Thanks Tip">
|
||||||
<rect key="frame" x="91" y="0.0" width="232.5" height="60"/>
|
<rect key="frame" x="90.5" y="0.0" width="233" height="60"/>
|
||||||
<subviews>
|
<subviews>
|
||||||
<imageView userInteractionEnabled="NO" contentMode="scaleToFill" image="tip_basic_black.png" translatesAutoresizingMaskIntoConstraints="NO" id="Z8P-ZK-aS0">
|
<imageView userInteractionEnabled="NO" contentMode="scaleToFill" image="tip_basic_black.png" translatesAutoresizingMaskIntoConstraints="NO" id="Z8P-ZK-aS0">
|
||||||
<rect key="frame" x="0.0" y="0.0" width="232.5" height="60"/>
|
<rect key="frame" x="0.0" y="0.0" width="233" height="60"/>
|
||||||
<rect key="contentStretch" x="0.15000000000000002" y="0.0" width="0.69999999999999973" height="1"/>
|
<rect key="contentStretch" x="0.15000000000000002" y="0.0" width="0.69999999999999973" height="1"/>
|
||||||
</imageView>
|
</imageView>
|
||||||
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" text="Why is Master Password free?" textAlignment="center" lineBreakMode="tailTruncation" minimumFontSize="10" translatesAutoresizingMaskIntoConstraints="NO" id="BLV-3x-Q0z">
|
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" text="Why is Master Password free?" textAlignment="center" lineBreakMode="tailTruncation" minimumFontSize="10" translatesAutoresizingMaskIntoConstraints="NO" id="BLV-3x-Q0z">
|
||||||
<rect key="frame" x="20" y="11.5" width="192.5" height="17"/>
|
<rect key="frame" x="20" y="11.5" width="193" height="17"/>
|
||||||
<fontDescription key="fontDescription" name="Exo2.0-Regular" family="Exo 2.0" pointSize="14"/>
|
<fontDescription key="fontDescription" name="Exo2.0-Regular" family="Exo 2.0" pointSize="14"/>
|
||||||
<color key="textColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
<color key="textColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||||
<nil key="highlightedColor"/>
|
<nil key="highlightedColor"/>
|
||||||
@@ -442,21 +442,12 @@
|
|||||||
<outlet property="nextAvatarButton" destination="fUK-gJ-NRE" id="5qo-lK-rSa"/>
|
<outlet property="nextAvatarButton" destination="fUK-gJ-NRE" id="5qo-lK-rSa"/>
|
||||||
<outlet property="preferencesTipContainer" destination="0Um-Ot-hI6" id="Cv8-Bp-ZZs"/>
|
<outlet property="preferencesTipContainer" destination="0Um-Ot-hI6" id="Cv8-Bp-ZZs"/>
|
||||||
<outlet property="previousAvatarButton" destination="9u7-pu-Wtv" id="Hgv-lN-S1n"/>
|
<outlet property="previousAvatarButton" destination="9u7-pu-Wtv" id="Hgv-lN-S1n"/>
|
||||||
<outlet property="searchDisplayController" destination="h98-GT-FoS" id="VvS-JO-rqq"/>
|
|
||||||
<outlet property="storeLoadingActivity" destination="VDd-oM-ZOO" id="MJ7-2f-e8n"/>
|
<outlet property="storeLoadingActivity" destination="VDd-oM-ZOO" id="MJ7-2f-e8n"/>
|
||||||
<outlet property="thanksTipContainer" destination="069-Pu-yXe" id="wWf-2X-Ryw"/>
|
<outlet property="thanksTipContainer" destination="069-Pu-yXe" id="wWf-2X-Ryw"/>
|
||||||
<outlet property="userSelectionContainer" destination="rWM-08-aab" id="Yme-hX-8P0"/>
|
<outlet property="userSelectionContainer" destination="rWM-08-aab" id="Yme-hX-8P0"/>
|
||||||
</connections>
|
</connections>
|
||||||
</viewController>
|
</viewController>
|
||||||
<placeholder placeholderIdentifier="IBFirstResponder" id="8hZ-Tb-wZw" userLabel="First Responder" sceneMemberID="firstResponder"/>
|
<placeholder placeholderIdentifier="IBFirstResponder" id="8hZ-Tb-wZw" userLabel="First Responder" sceneMemberID="firstResponder"/>
|
||||||
<searchDisplayController id="h98-GT-FoS">
|
|
||||||
<connections>
|
|
||||||
<outlet property="delegate" destination="S8q-YF-Kt9" id="hyY-rf-2x2"/>
|
|
||||||
<outlet property="searchContentsController" destination="S8q-YF-Kt9" id="2RA-rs-GhH"/>
|
|
||||||
<outlet property="searchResultsDataSource" destination="S8q-YF-Kt9" id="Cdu-go-UBQ"/>
|
|
||||||
<outlet property="searchResultsDelegate" destination="S8q-YF-Kt9" id="xxe-xE-sFM"/>
|
|
||||||
</connections>
|
|
||||||
</searchDisplayController>
|
|
||||||
</objects>
|
</objects>
|
||||||
<point key="canvasLocation" x="2041" y="226"/>
|
<point key="canvasLocation" x="2041" y="226"/>
|
||||||
</scene>
|
</scene>
|
||||||
@@ -531,12 +522,23 @@
|
|||||||
<view key="view" contentMode="scaleToFill" id="c4P-nn-PjR">
|
<view key="view" contentMode="scaleToFill" id="c4P-nn-PjR">
|
||||||
<rect key="frame" x="0.0" y="0.0" width="414" height="896"/>
|
<rect key="frame" x="0.0" y="0.0" width="414" height="896"/>
|
||||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||||
|
<subviews>
|
||||||
|
<containerView opaque="NO" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="qca-aL-Un8">
|
||||||
|
<rect key="frame" x="0.0" y="0.0" width="414" height="896"/>
|
||||||
|
<connections>
|
||||||
|
<segue destination="Ac5-na-hOV" kind="embed" identifier="root" id="x4h-Hl-KXD"/>
|
||||||
|
</connections>
|
||||||
|
</containerView>
|
||||||
|
</subviews>
|
||||||
<color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
<color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||||
|
<constraints>
|
||||||
|
<constraint firstItem="qca-aL-Un8" firstAttribute="top" secondItem="c4P-nn-PjR" secondAttribute="top" id="7ix-Oo-ELN"/>
|
||||||
|
<constraint firstAttribute="bottom" secondItem="qca-aL-Un8" secondAttribute="bottom" id="JRU-fk-cPG"/>
|
||||||
|
<constraint firstItem="qca-aL-Un8" firstAttribute="leading" secondItem="c4P-nn-PjR" secondAttribute="leading" id="OAO-XC-DQ1"/>
|
||||||
|
<constraint firstAttribute="trailing" secondItem="qca-aL-Un8" secondAttribute="trailing" id="R9n-bd-GVl"/>
|
||||||
|
</constraints>
|
||||||
</view>
|
</view>
|
||||||
<navigationItem key="navigationItem" id="V6W-ql-3TD"/>
|
<navigationItem key="navigationItem" id="V6W-ql-3TD"/>
|
||||||
<connections>
|
|
||||||
<segue destination="Ac5-na-hOV" kind="custom" identifier="root" customClass="MPRootSegue" id="UKS-gd-oD2"/>
|
|
||||||
</connections>
|
|
||||||
</viewController>
|
</viewController>
|
||||||
<placeholder placeholderIdentifier="IBFirstResponder" id="fQY-fV-sIe" userLabel="First Responder" sceneMemberID="firstResponder"/>
|
<placeholder placeholderIdentifier="IBFirstResponder" id="fQY-fV-sIe" userLabel="First Responder" sceneMemberID="firstResponder"/>
|
||||||
</objects>
|
</objects>
|
||||||
@@ -557,12 +559,25 @@
|
|||||||
<imageView userInteractionEnabled="NO" contentMode="scaleAspectFill" image="background.png" translatesAutoresizingMaskIntoConstraints="NO" id="Lkg-xn-bce" userLabel="Background">
|
<imageView userInteractionEnabled="NO" contentMode="scaleAspectFill" image="background.png" translatesAutoresizingMaskIntoConstraints="NO" id="Lkg-xn-bce" userLabel="Background">
|
||||||
<rect key="frame" x="0.0" y="0.0" width="414" height="896"/>
|
<rect key="frame" x="0.0" y="0.0" width="414" height="896"/>
|
||||||
</imageView>
|
</imageView>
|
||||||
|
<containerView opaque="NO" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="91I-wN-JQb">
|
||||||
|
<rect key="frame" x="0.0" y="0.0" width="414" height="896"/>
|
||||||
|
<userDefinedRuntimeAttributes>
|
||||||
|
<userDefinedRuntimeAttribute type="boolean" keyPath="ignoreTouches" value="YES"/>
|
||||||
|
</userDefinedRuntimeAttributes>
|
||||||
|
<connections>
|
||||||
|
<segue destination="S8q-YF-Kt9" kind="embed" identifier="users" id="GzD-Zv-DzW"/>
|
||||||
|
</connections>
|
||||||
|
</containerView>
|
||||||
</subviews>
|
</subviews>
|
||||||
<constraints>
|
<constraints>
|
||||||
|
<constraint firstItem="91I-wN-JQb" firstAttribute="leading" secondItem="fkJ-D0-yue" secondAttribute="leading" id="E4w-Dw-Vip"/>
|
||||||
<constraint firstItem="Lkg-xn-bce" firstAttribute="top" secondItem="fkJ-D0-yue" secondAttribute="top" id="EIy-Cd-0vW"/>
|
<constraint firstItem="Lkg-xn-bce" firstAttribute="top" secondItem="fkJ-D0-yue" secondAttribute="top" id="EIy-Cd-0vW"/>
|
||||||
|
<constraint firstItem="91I-wN-JQb" firstAttribute="top" secondItem="fkJ-D0-yue" secondAttribute="top" id="EeB-9X-PEK"/>
|
||||||
<constraint firstAttribute="trailing" secondItem="Lkg-xn-bce" secondAttribute="trailing" id="ROW-fK-z92"/>
|
<constraint firstAttribute="trailing" secondItem="Lkg-xn-bce" secondAttribute="trailing" id="ROW-fK-z92"/>
|
||||||
<constraint firstItem="Lkg-xn-bce" firstAttribute="leading" secondItem="fkJ-D0-yue" secondAttribute="leading" id="UH5-Kk-taJ"/>
|
<constraint firstItem="Lkg-xn-bce" firstAttribute="leading" secondItem="fkJ-D0-yue" secondAttribute="leading" id="UH5-Kk-taJ"/>
|
||||||
|
<constraint firstAttribute="bottom" secondItem="91I-wN-JQb" secondAttribute="bottom" id="mxv-9s-jxT"/>
|
||||||
<constraint firstAttribute="bottom" secondItem="Lkg-xn-bce" secondAttribute="bottom" id="txR-pf-v3l"/>
|
<constraint firstAttribute="bottom" secondItem="Lkg-xn-bce" secondAttribute="bottom" id="txR-pf-v3l"/>
|
||||||
|
<constraint firstAttribute="trailing" secondItem="91I-wN-JQb" secondAttribute="trailing" id="uef-ig-RRl"/>
|
||||||
</constraints>
|
</constraints>
|
||||||
</view>
|
</view>
|
||||||
<navigationItem key="navigationItem" id="MPa-zX-Kaq"/>
|
<navigationItem key="navigationItem" id="MPa-zX-Kaq"/>
|
||||||
@@ -570,7 +585,6 @@
|
|||||||
<connections>
|
<connections>
|
||||||
<segue destination="osn-5H-SWW" kind="custom" identifier="emergency" customClass="MPOverlaySegue" id="gtX-Cx-AA2"/>
|
<segue destination="osn-5H-SWW" kind="custom" identifier="emergency" customClass="MPOverlaySegue" id="gtX-Cx-AA2"/>
|
||||||
<segue destination="nkY-z6-8jd" kind="custom" identifier="passwords" customClass="MPSitesSegue" id="Ozp-YT-Utx"/>
|
<segue destination="nkY-z6-8jd" kind="custom" identifier="passwords" customClass="MPSitesSegue" id="Ozp-YT-Utx"/>
|
||||||
<segue destination="S8q-YF-Kt9" kind="custom" identifier="users" customClass="MPRootSegue" id="StK-nr-nps"/>
|
|
||||||
</connections>
|
</connections>
|
||||||
</viewController>
|
</viewController>
|
||||||
<placeholder placeholderIdentifier="IBFirstResponder" id="F33-Fe-Tb6" userLabel="First Responder" sceneMemberID="firstResponder"/>
|
<placeholder placeholderIdentifier="IBFirstResponder" id="F33-Fe-Tb6" userLabel="First Responder" sceneMemberID="firstResponder"/>
|
||||||
@@ -1135,7 +1149,8 @@ Note that this feature requires you enable the Save Password option and have pur
|
|||||||
<collectionView opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" minimumZoomScale="0.0" maximumZoomScale="0.0" keyboardDismissMode="interactive" dataMode="prototypes" translatesAutoresizingMaskIntoConstraints="NO" id="aXw-tn-8Sj" userLabel="Password Collection">
|
<collectionView opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" minimumZoomScale="0.0" maximumZoomScale="0.0" keyboardDismissMode="interactive" dataMode="prototypes" translatesAutoresizingMaskIntoConstraints="NO" id="aXw-tn-8Sj" userLabel="Password Collection">
|
||||||
<rect key="frame" x="0.0" y="0.0" width="414" height="896"/>
|
<rect key="frame" x="0.0" y="0.0" width="414" height="896"/>
|
||||||
<color key="backgroundColor" red="0.0" green="0.0" blue="0.0" alpha="0.0" colorSpace="custom" customColorSpace="sRGB"/>
|
<color key="backgroundColor" red="0.0" green="0.0" blue="0.0" alpha="0.0" colorSpace="custom" customColorSpace="sRGB"/>
|
||||||
<collectionViewFlowLayout key="collectionViewLayout" minimumLineSpacing="10" minimumInteritemSpacing="10" sectionInsetReference="safeArea" id="Mv1-29-TWx">
|
<edgeInsets key="layoutMargins" top="100" left="0.0" bottom="0.0" right="0.0"/>
|
||||||
|
<collectionViewFlowLayout key="collectionViewLayout" minimumLineSpacing="10" minimumInteritemSpacing="10" sectionInsetReference="layoutMargins" id="Mv1-29-TWx">
|
||||||
<size key="itemSize" width="355" height="100"/>
|
<size key="itemSize" width="355" height="100"/>
|
||||||
<size key="headerReferenceSize" width="0.0" height="0.0"/>
|
<size key="headerReferenceSize" width="0.0" height="0.0"/>
|
||||||
<size key="footerReferenceSize" width="0.0" height="0.0"/>
|
<size key="footerReferenceSize" width="0.0" height="0.0"/>
|
||||||
@@ -1143,7 +1158,7 @@ Note that this feature requires you enable the Save Password option and have pur
|
|||||||
</collectionViewFlowLayout>
|
</collectionViewFlowLayout>
|
||||||
<cells>
|
<cells>
|
||||||
<collectionViewCell opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" reuseIdentifier="MPSiteCell" id="W2g-yv-V3V" customClass="MPSiteCell">
|
<collectionViewCell opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" reuseIdentifier="MPSiteCell" id="W2g-yv-V3V" customClass="MPSiteCell">
|
||||||
<rect key="frame" x="29.5" y="10" width="355" height="100"/>
|
<rect key="frame" x="29.5" y="110" width="355" height="100"/>
|
||||||
<autoresizingMask key="autoresizingMask"/>
|
<autoresizingMask key="autoresizingMask"/>
|
||||||
<view key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" insetsLayoutMarginsFromSafeArea="NO">
|
<view key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" insetsLayoutMarginsFromSafeArea="NO">
|
||||||
<rect key="frame" x="0.0" y="0.0" width="355" height="100"/>
|
<rect key="frame" x="0.0" y="0.0" width="355" height="100"/>
|
||||||
@@ -2226,7 +2241,7 @@ Suspendisse potenti. Etiam ut nisi id augue tempor ultrices et sit amet sapien.
|
|||||||
<dataDetectorType key="dataDetectorTypes" link="YES"/>
|
<dataDetectorType key="dataDetectorTypes" link="YES"/>
|
||||||
</textView>
|
</textView>
|
||||||
<toolbar contentMode="scaleToFill" barStyle="black" translatesAutoresizingMaskIntoConstraints="NO" id="WmH-JB-jp2">
|
<toolbar contentMode="scaleToFill" barStyle="black" translatesAutoresizingMaskIntoConstraints="NO" id="WmH-JB-jp2">
|
||||||
<rect key="frame" x="0.0" y="764" width="414" height="49"/>
|
<rect key="frame" x="0.0" y="769" width="414" height="44"/>
|
||||||
<items>
|
<items>
|
||||||
<barButtonItem systemItem="compose" id="BSV-3i-01h">
|
<barButtonItem systemItem="compose" id="BSV-3i-01h">
|
||||||
<connections>
|
<connections>
|
||||||
@@ -2241,7 +2256,7 @@ Suspendisse potenti. Etiam ut nisi id augue tempor ultrices et sit amet sapien.
|
|||||||
<barButtonItem systemItem="flexibleSpace" id="Lp4-ss-KxI"/>
|
<barButtonItem systemItem="flexibleSpace" id="Lp4-ss-KxI"/>
|
||||||
<barButtonItem style="plain" id="aMS-HH-mnE">
|
<barButtonItem style="plain" id="aMS-HH-mnE">
|
||||||
<segmentedControl key="customView" opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="top" segmentControlStyle="bar" selectedSegmentIndex="0" id="lxp-wx-uCy">
|
<segmentedControl key="customView" opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="top" segmentControlStyle="bar" selectedSegmentIndex="0" id="lxp-wx-uCy">
|
||||||
<rect key="frame" x="267" y="11" width="127" height="32"/>
|
<rect key="frame" x="267" y="6" width="127" height="32"/>
|
||||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
||||||
<segments>
|
<segments>
|
||||||
<segment title="Normal"/>
|
<segment title="Normal"/>
|
||||||
@@ -2741,7 +2756,7 @@ Invested: 3.7 work hours</string>
|
|||||||
<rect key="frame" x="188.5" y="20" width="37" height="37"/>
|
<rect key="frame" x="188.5" y="20" width="37" height="37"/>
|
||||||
</activityIndicatorView>
|
</activityIndicatorView>
|
||||||
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" horizontalCompressionResistancePriority="751" verticalCompressionResistancePriority="751" text="Loading products..." textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" minimumFontSize="12" adjustsLetterSpacingToFitWidth="YES" translatesAutoresizingMaskIntoConstraints="NO" id="NPg-it-juF">
|
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" horizontalCompressionResistancePriority="751" verticalCompressionResistancePriority="751" text="Loading products..." textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" minimumFontSize="12" adjustsLetterSpacingToFitWidth="YES" translatesAutoresizingMaskIntoConstraints="NO" id="NPg-it-juF">
|
||||||
<rect key="frame" x="134.5" y="97" width="145.5" height="25"/>
|
<rect key="frame" x="134" y="97" width="146" height="25"/>
|
||||||
<fontDescription key="fontDescription" name="Exo2.0-Regular" family="Exo 2.0" pointSize="17"/>
|
<fontDescription key="fontDescription" name="Exo2.0-Regular" family="Exo 2.0" pointSize="17"/>
|
||||||
<color key="textColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
<color key="textColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||||
<nil key="highlightedColor"/>
|
<nil key="highlightedColor"/>
|
||||||
@@ -3257,7 +3272,7 @@ Ut in geometria, prima si dederis, danda sunt omnia. Nonne igitur tibi videntur,
|
|||||||
</scene>
|
</scene>
|
||||||
</scenes>
|
</scenes>
|
||||||
<inferredMetricsTieBreakers>
|
<inferredMetricsTieBreakers>
|
||||||
<segue reference="k2G-nL-x3l"/>
|
<segue reference="Ql4-wf-T8u"/>
|
||||||
<segue reference="gtb-zE-u9H"/>
|
<segue reference="gtb-zE-u9H"/>
|
||||||
</inferredMetricsTieBreakers>
|
</inferredMetricsTieBreakers>
|
||||||
<color key="tintColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
|
<color key="tintColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
|
||||||
|
|||||||
@@ -346,7 +346,7 @@ public interface MPAlgorithm {
|
|||||||
@Nonnull
|
@Nonnull
|
||||||
@Override
|
@Override
|
||||||
public Version version() {
|
public Version version() {
|
||||||
return MPAlgorithm.Version.V0;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nonnull
|
@Nonnull
|
||||||
|
|||||||
@@ -20,7 +20,6 @@ package com.lyndir.masterpassword;
|
|||||||
|
|
||||||
import com.google.common.base.Preconditions;
|
import com.google.common.base.Preconditions;
|
||||||
import com.google.common.primitives.UnsignedInteger;
|
import com.google.common.primitives.UnsignedInteger;
|
||||||
import com.lyndir.lhunath.opal.system.CodeUtils;
|
|
||||||
import com.lyndir.lhunath.opal.system.logging.Logger;
|
import com.lyndir.lhunath.opal.system.logging.Logger;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.EnumMap;
|
import java.util.EnumMap;
|
||||||
@@ -56,6 +55,7 @@ public class MPMasterKey {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@SuppressWarnings("deprecation")
|
||||||
protected void finalize()
|
protected void finalize()
|
||||||
throws Throwable {
|
throws Throwable {
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user