mirror of
https://github.com/twofas/2fas-ios.git
synced 2024-11-22 02:10:19 +01:00
Merge pull request #121 from twofas/feature/TF-1571
[TF-1571] Apple Watch settings
This commit is contained in:
commit
26a22e75ad
@ -23,9 +23,9 @@
|
||||
"color-space" : "srgb",
|
||||
"components" : {
|
||||
"alpha" : "1.000",
|
||||
"blue" : "0.137",
|
||||
"green" : "0.110",
|
||||
"red" : "0.929"
|
||||
"blue" : "0x22",
|
||||
"green" : "0x1C",
|
||||
"red" : "0xEC"
|
||||
}
|
||||
},
|
||||
"idiom" : "universal"
|
||||
|
@ -5,9 +5,9 @@
|
||||
"color-space" : "srgb",
|
||||
"components" : {
|
||||
"alpha" : "1.000",
|
||||
"blue" : "0.480",
|
||||
"green" : "0.450",
|
||||
"red" : "1.000"
|
||||
"blue" : "0x7A",
|
||||
"green" : "0x72",
|
||||
"red" : "0xFF"
|
||||
}
|
||||
},
|
||||
"idiom" : "universal"
|
||||
@ -23,9 +23,9 @@
|
||||
"color-space" : "srgb",
|
||||
"components" : {
|
||||
"alpha" : "1.000",
|
||||
"blue" : "0.140",
|
||||
"green" : "0.110",
|
||||
"red" : "0.744"
|
||||
"blue" : "0x23",
|
||||
"green" : "0x1C",
|
||||
"red" : "0xBD"
|
||||
}
|
||||
},
|
||||
"idiom" : "universal"
|
||||
|
@ -5,9 +5,9 @@
|
||||
"color-space" : "srgb",
|
||||
"components" : {
|
||||
"alpha" : "1.000",
|
||||
"blue" : "0.137",
|
||||
"green" : "0.110",
|
||||
"red" : "0.929"
|
||||
"blue" : "0x22",
|
||||
"green" : "0x1C",
|
||||
"red" : "0xEC"
|
||||
}
|
||||
},
|
||||
"idiom" : "universal"
|
||||
|
@ -8,11 +8,15 @@
|
||||
|
||||
/* Begin PBXBuildFile section */
|
||||
8F00E46A2C23953B001F15AD /* SortTokensView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8F00E4692C23953B001F15AD /* SortTokensView.swift */; };
|
||||
8F872DE92C24EE2600160D14 /* SortTokensPresenter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8F872DE82C24EE2600160D14 /* SortTokensPresenter.swift */; };
|
||||
8F872DEB2C24EE5500160D14 /* SortTokensInteractor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8F872DEA2C24EE5500160D14 /* SortTokensInteractor.swift */; };
|
||||
8F43E7002C4C50DD0006D380 /* AppleWatchPresenter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8F43E6FF2C4C50DD0006D380 /* AppleWatchPresenter.swift */; };
|
||||
8F43E7032C4C511A0006D380 /* AppleWatchFlowController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8F43E7022C4C511A0006D380 /* AppleWatchFlowController.swift */; };
|
||||
8F594C422C3027160066562F /* AppleWatchView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8F594C412C3027160066562F /* AppleWatchView.swift */; };
|
||||
8F594C442C3054F90066562F /* AppleWatchViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8F594C432C3054F90066562F /* AppleWatchViewController.swift */; };
|
||||
8F5C0C6C2BFFAC8A00D73ADE /* TwoFAS.xcdatamodeld in Sources */ = {isa = PBXBuildFile; fileRef = 8F5C0C6A2BFFAC8900D73ADE /* TwoFAS.xcdatamodeld */; };
|
||||
8F5C0C6F2BFFACA900D73ADE /* Sync.xcdatamodeld in Sources */ = {isa = PBXBuildFile; fileRef = 8F5C0C6D2BFFACA900D73ADE /* Sync.xcdatamodeld */; };
|
||||
8F7952532C01D1940053F776 /* KeyboardButtonStyle.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8F7952522C01D1940053F776 /* KeyboardButtonStyle.swift */; };
|
||||
8F872DE92C24EE2600160D14 /* SortTokensPresenter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8F872DE82C24EE2600160D14 /* SortTokensPresenter.swift */; };
|
||||
8F872DEB2C24EE5500160D14 /* SortTokensInteractor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8F872DEA2C24EE5500160D14 /* SortTokensInteractor.swift */; };
|
||||
C200E49E1FB3911B00D7C748 /* Storage.h in Headers */ = {isa = PBXBuildFile; fileRef = C200E49C1FB3911B00D7C748 /* Storage.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
C200E4A11FB3911B00D7C748 /* Storage.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C200E49A1FB3911B00D7C748 /* Storage.framework */; };
|
||||
C200E4A21FB3911B00D7C748 /* Storage.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = C200E49A1FB3911B00D7C748 /* Storage.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
|
||||
@ -1880,12 +1884,15 @@
|
||||
|
||||
/* Begin PBXFileReference section */
|
||||
8F00E4692C23953B001F15AD /* SortTokensView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SortTokensView.swift; sourceTree = "<group>"; };
|
||||
8F872DE82C24EE2600160D14 /* SortTokensPresenter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SortTokensPresenter.swift; sourceTree = "<group>"; };
|
||||
8F872DEA2C24EE5500160D14 /* SortTokensInteractor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SortTokensInteractor.swift; sourceTree = "<group>"; };
|
||||
8F43E6FF2C4C50DD0006D380 /* AppleWatchPresenter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppleWatchPresenter.swift; sourceTree = "<group>"; };
|
||||
8F43E7022C4C511A0006D380 /* AppleWatchFlowController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppleWatchFlowController.swift; sourceTree = "<group>"; };
|
||||
8F594C412C3027160066562F /* AppleWatchView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppleWatchView.swift; sourceTree = "<group>"; };
|
||||
8F594C432C3054F90066562F /* AppleWatchViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppleWatchViewController.swift; sourceTree = "<group>"; };
|
||||
8F5C0C6B2BFFAC8900D73ADE /* TwoFAS.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = TwoFAS.xcdatamodel; sourceTree = "<group>"; };
|
||||
8F5C0C6E2BFFACA900D73ADE /* Sync.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = Sync.xcdatamodel; sourceTree = "<group>"; };
|
||||
8F7952522C01D1940053F776 /* KeyboardButtonStyle.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KeyboardButtonStyle.swift; sourceTree = "<group>"; };
|
||||
8FD3F0852C37324B0042092E /* el */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = el; path = el.lproj/LaunchScreen.strings; sourceTree = "<group>"; };
|
||||
8F872DE82C24EE2600160D14 /* SortTokensPresenter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SortTokensPresenter.swift; sourceTree = "<group>"; };
|
||||
8F872DEA2C24EE5500160D14 /* SortTokensInteractor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SortTokensInteractor.swift; sourceTree = "<group>"; };
|
||||
8FD3F0862C37324B0042092E /* el */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = el; path = el.lproj/TwoFASWidget.strings; sourceTree = "<group>"; };
|
||||
8FD3F0872C37324B0042092E /* el */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = el; path = el.lproj/Localizable.strings; sourceTree = "<group>"; };
|
||||
8FD3F0882C37324B0042092E /* el */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = el; path = el.lproj/InfoPlist.strings; sourceTree = "<group>"; };
|
||||
@ -3326,8 +3333,43 @@
|
||||
8F872DEA2C24EE5500160D14 /* SortTokensInteractor.swift */,
|
||||
);
|
||||
path = SortTokens;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
8F43E6FD2C4C50A60006D380 /* View */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
8F594C412C3027160066562F /* AppleWatchView.swift */,
|
||||
8F594C432C3054F90066562F /* AppleWatchViewController.swift */,
|
||||
);
|
||||
path = View;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
8F43E6FE2C4C50C70006D380 /* Presenter */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
8F43E6FF2C4C50DD0006D380 /* AppleWatchPresenter.swift */,
|
||||
);
|
||||
path = Presenter;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
8F43E7012C4C51060006D380 /* Flow */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
8F43E7022C4C511A0006D380 /* AppleWatchFlowController.swift */,
|
||||
);
|
||||
path = Flow;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
8F594C402C3024E60066562F /* AppleWatch */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
8F43E7012C4C51060006D380 /* Flow */,
|
||||
8F43E6FE2C4C50C70006D380 /* Presenter */,
|
||||
8F43E6FD2C4C50A60006D380 /* View */,
|
||||
);
|
||||
path = AppleWatch;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
8F7952502C01D1770053F776 /* CommonSwiftUI */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
@ -3735,6 +3777,7 @@
|
||||
C21111E1274AB8C100CA7C78 /* Settings */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
8F594C402C3024E60066562F /* AppleWatch */,
|
||||
C2B1208529D767150020281E /* Appearance */,
|
||||
C2CC0A4129D08D7700677A7B /* ExternalImportInstructions */,
|
||||
C2CC0A3429D056CF00677A7B /* ExternalImport */,
|
||||
@ -9811,6 +9854,7 @@
|
||||
C21B1B312A882A920021CAF1 /* AddingServiceTOTPTimerView.swift in Sources */,
|
||||
C27BE517275D6ACC0090CA12 /* BackupMenuModuleInteractor.swift in Sources */,
|
||||
C2B39E5B29F5D0AA00EC31F6 /* TokensServiceName.swift in Sources */,
|
||||
8F594C422C3027160066562F /* AppleWatchView.swift in Sources */,
|
||||
C27D543F275D393D001E9ABF /* BackupMenuPresenter.swift in Sources */,
|
||||
C25C91CF2B08E84800E58729 /* AddingServiceManuallyNavigationFlowController.swift in Sources */,
|
||||
C23FD51228146E2E00E4E9C5 /* ComposeServiceWebExtensionPresenter.swift in Sources */,
|
||||
@ -9833,6 +9877,7 @@
|
||||
C2035AED245DCAAD00C482D2 /* MainContainerBottomNavigationGenerator.swift in Sources */,
|
||||
C2B2ED2427C44BF300332255 /* AdvancedAlertViewController.swift in Sources */,
|
||||
C25B221927C199B80052AAC4 /* ComposeServicePrivateKeyCell.swift in Sources */,
|
||||
8F43E7002C4C50DD0006D380 /* AppleWatchPresenter.swift in Sources */,
|
||||
C2ADD6122752DC1E0010F5E7 /* SettingsMenuFlowController.swift in Sources */,
|
||||
C2C1DDDF27CAA7F2002C7867 /* ComposeServiceAdvancedEditFlowController.swift in Sources */,
|
||||
C263F45A29900DED009B0837 /* MainMenuModels.swift in Sources */,
|
||||
@ -10039,6 +10084,7 @@
|
||||
C20524C32807620500B2B20C /* NavigationBarHiddenHostingController.swift in Sources */,
|
||||
C2FDEE57279C8FF8002CAB9E /* SwiftUIButtons.swift in Sources */,
|
||||
C22E6FA121E2666B00A2E66B /* CircularShape.swift in Sources */,
|
||||
8F594C442C3054F90066562F /* AppleWatchViewController.swift in Sources */,
|
||||
C2F7FE092A8ABA25004B2C95 /* AddingServiceManuallyView.swift in Sources */,
|
||||
C2AC221327661BA300271402 /* ExporterPasswordProtectionViewController.swift in Sources */,
|
||||
C2B2ED1E27C4349100332255 /* AdvancedAlert.swift in Sources */,
|
||||
@ -10082,6 +10128,7 @@
|
||||
C296D4D42A8979BF005F05E2 /* BrowserExtensionPairingNavigationFlowController.swift in Sources */,
|
||||
C2C66F951FE068CC00AD5A1C /* TokensViewController.swift in Sources */,
|
||||
C2EBDFFC2AC44750008FD744 /* GuideMenuViewController.swift in Sources */,
|
||||
8F43E7032C4C511A0006D380 /* AppleWatchFlowController.swift in Sources */,
|
||||
C240487C27656DB40076376E /* ImporterFileErrorFlowController.swift in Sources */,
|
||||
C2A74FD72610D3A8007E5AB3 /* TintColor.swift in Sources */,
|
||||
C2CC0A3A29D0580B00677A7B /* ExternalImportViewController.swift in Sources */,
|
||||
@ -11198,7 +11245,6 @@
|
||||
C2BBD24C2B813162009A91FB /* uk */,
|
||||
C2BBD24D2B813162009A91FB /* de */,
|
||||
C2BBD24E2B813162009A91FB /* pl */,
|
||||
8FD3F08A2C3732E20042092E /* el */,
|
||||
);
|
||||
name = Localizable.strings;
|
||||
sourceTree = "<group>";
|
||||
|
@ -148,6 +148,7 @@ enum Theme {
|
||||
static let background = ThemeColor.background
|
||||
static let backgroundLight = ThemeColor.backgroundLight
|
||||
static let placeholder = ThemeColor.divider
|
||||
static let tertiary = ThemeColor.tertiary
|
||||
}
|
||||
}
|
||||
|
||||
@ -211,6 +212,8 @@ enum Theme {
|
||||
static let warning = UIFont.systemFont(ofSize: 13, weight: .medium)
|
||||
static let iconLabel = UIFont.systemFont(ofSize: 13, weight: .bold)
|
||||
static let iconLabelSmall = UIFont.systemFont(ofSize: 12, weight: .bold)
|
||||
static let iconLabelLarge = UIFont.systemFont(ofSize: 15, weight: .bold)
|
||||
static let iconLabelExtraLarge = UIFont.systemFont(ofSize: 15, weight: .bold)
|
||||
static let sectionHeader = UIFont.systemFont(ofSize: 13, weight: .regular)
|
||||
static let iconLabelInputTitle = UIFont.systemFont(ofSize: 22, weight: .light)
|
||||
static let tabBar = UIFont.systemFont(ofSize: 10, weight: .semibold)
|
||||
@ -258,7 +261,9 @@ enum Theme {
|
||||
static let mediumMargin: CGFloat = (3 * ThemeMetrics.margin) / 2
|
||||
/// 16
|
||||
static let doubleMargin: CGFloat = 2 * ThemeMetrics.margin
|
||||
|
||||
/// 32
|
||||
static let quadrupleMargin: CGFloat = 4 * ThemeMetrics.margin
|
||||
|
||||
static let lineWidth: CGFloat = ThemeMetrics.lineWidth
|
||||
static let separatorHeight: CGFloat = 0.5
|
||||
/// 6
|
||||
|
22
TwoFAS/TwoFAS/Other/Assets.xcassets/AppleWatch.imageset/Contents.json
vendored
Normal file
22
TwoFAS/TwoFAS/Other/Assets.xcassets/AppleWatch.imageset/Contents.json
vendored
Normal file
@ -0,0 +1,22 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"filename" : "appleWatch.pdf",
|
||||
"idiom" : "universal"
|
||||
},
|
||||
{
|
||||
"appearances" : [
|
||||
{
|
||||
"appearance" : "luminosity",
|
||||
"value" : "dark"
|
||||
}
|
||||
],
|
||||
"filename" : "appleWatchDark.pdf",
|
||||
"idiom" : "universal"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
BIN
TwoFAS/TwoFAS/Other/Assets.xcassets/AppleWatch.imageset/appleWatch.pdf
vendored
Normal file
BIN
TwoFAS/TwoFAS/Other/Assets.xcassets/AppleWatch.imageset/appleWatch.pdf
vendored
Normal file
Binary file not shown.
BIN
TwoFAS/TwoFAS/Other/Assets.xcassets/AppleWatch.imageset/appleWatchDark.pdf
vendored
Normal file
BIN
TwoFAS/TwoFAS/Other/Assets.xcassets/AppleWatch.imageset/appleWatchDark.pdf
vendored
Normal file
Binary file not shown.
12
TwoFAS/TwoFAS/Other/Assets.xcassets/Settings/SettingsWatch.imageset/Contents.json
vendored
Normal file
12
TwoFAS/TwoFAS/Other/Assets.xcassets/Settings/SettingsWatch.imageset/Contents.json
vendored
Normal file
@ -0,0 +1,12 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"filename" : "SettingsWatch.pdf",
|
||||
"idiom" : "universal"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
BIN
TwoFAS/TwoFAS/Other/Assets.xcassets/Settings/SettingsWatch.imageset/SettingsWatch.pdf
vendored
Normal file
BIN
TwoFAS/TwoFAS/Other/Assets.xcassets/Settings/SettingsWatch.imageset/SettingsWatch.pdf
vendored
Normal file
Binary file not shown.
@ -29,6 +29,7 @@ internal enum Asset {
|
||||
internal static let imageIcon = ImageAsset(name: "imageIcon")
|
||||
internal static let keybordIcon = ImageAsset(name: "keybordIcon")
|
||||
internal static let alertIcon = ImageAsset(name: "AlertIcon")
|
||||
internal static let appleWatch = ImageAsset(name: "AppleWatch")
|
||||
internal static let authRequestQuestion = ImageAsset(name: "AuthRequestQuestion")
|
||||
internal static let deleteSettingsIcon = ImageAsset(name: "DeleteSettingsIcon")
|
||||
internal static let backupDeleted = ImageAsset(name: "backupDeleted")
|
||||
@ -156,6 +157,7 @@ internal enum Asset {
|
||||
internal static let settingsTouchID = ImageAsset(name: "SettingsTouchID")
|
||||
internal static let settingsTrash = ImageAsset(name: "SettingsTrash")
|
||||
internal static let settingsValut = ImageAsset(name: "SettingsValut")
|
||||
internal static let settingsWatch = ImageAsset(name: "SettingsWatch")
|
||||
internal static let settingsWidget = ImageAsset(name: "SettingsWidget")
|
||||
internal static let settingsWriteReview = ImageAsset(name: "SettingsWriteReview")
|
||||
internal static let trashEmptyIcon = ImageAsset(name: "TrashEmptyIcon")
|
||||
|
@ -289,6 +289,18 @@ internal enum T {
|
||||
/// Active search
|
||||
internal static let toggleActiveSearch = T.tr("Localizable", "appearance__toggle_active_search", fallback: "Active search")
|
||||
}
|
||||
internal enum AppleWatch {
|
||||
/// Install 2FAS Auth via Watch app
|
||||
internal static let installationFirstStep = T.tr("Localizable", "appleWatch__installation_first_step", fallback: "Install 2FAS Auth via Watch app")
|
||||
/// Open Watch app
|
||||
internal static let installationFirstStepLink = T.tr("Localizable", "appleWatch__installation_first_step_link", fallback: "Open Watch app")
|
||||
/// 2FAS Apple Watch app installation
|
||||
internal static let installationInfoTitle = T.tr("Localizable", "appleWatch__installation_info_title", fallback: "2FAS Apple Watch app installation")
|
||||
/// Ensure your iCloud Sync is enabled
|
||||
internal static let installationSecondStep = T.tr("Localizable", "appleWatch__installation_second_step", fallback: "Ensure your iCloud Sync is enabled")
|
||||
/// Go to 2FAS Backup settings
|
||||
internal static let installationSecondStepLink = T.tr("Localizable", "appleWatch__installation_second_step_link", fallback: "Go to 2FAS Backup settings")
|
||||
}
|
||||
internal enum Backup {
|
||||
/// 2FAS Backup
|
||||
internal static let _2fasBackup = T.tr("Localizable", "backup__2fas_backup", fallback: "2FAS Backup")
|
||||
@ -378,9 +390,9 @@ internal enum T {
|
||||
internal static let incorrectCharacterError = T.tr("Localizable", "backup__incorrect_character_error", fallback: "Incorrect character. Use only letter A-Z, a-z, digits and special characters: -_/!#$%&+*~@?=^.,'(){}[]:;<>|")
|
||||
/// Incorrect Password
|
||||
internal static let incorrectPassword = T.tr("Localizable", "backup__incorrect_password", fallback: "Incorrect Password")
|
||||
/// Couldn't backup tokens because "%@" secret contains illegal characters. Remove it from list and try again
|
||||
/// Couldn't backup tokens because "%@" secret contains invalid characters. Remove it from list and try again
|
||||
internal static func incorrectSecret(_ p1: Any) -> String {
|
||||
return T.tr("Localizable", "backup__incorrect_secret", String(describing: p1), fallback: "Couldn't backup tokens because \"%@\" secret contains illegal characters. Remove it from list and try again")
|
||||
return T.tr("Localizable", "backup__incorrect_secret", String(describing: p1), fallback: "Couldn't backup tokens because \"%@\" secret contains invalid characters. Remove it from list and try again")
|
||||
}
|
||||
/// Local file
|
||||
internal static let localFileTitle = T.tr("Localizable", "backup__local_file_title", fallback: "Local file")
|
||||
@ -1020,6 +1032,8 @@ internal enum T {
|
||||
internal static let appSecurity = T.tr("Localizable", "settings__app_security", fallback: "App security")
|
||||
/// Appearance
|
||||
internal static let appearance = T.tr("Localizable", "settings__appearance", fallback: "Appearance")
|
||||
/// Apple Watch
|
||||
internal static let appleWatch = T.tr("Localizable", "settings__apple_watch", fallback: "Apple Watch")
|
||||
/// Backup and Synchronization
|
||||
internal static let backupAndSynchronization = T.tr("Localizable", "settings__backup_and_synchronization", fallback: "Backup and Synchronization")
|
||||
/// Biometric Authentication
|
||||
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -0,0 +1,60 @@
|
||||
//
|
||||
// This file is part of the 2FAS iOS app (https://github.com/twofas/2fas-ios)
|
||||
// Copyright © 2024 Two Factor Authentication Service, Inc.
|
||||
// Contributed by Grzegorz Machnio. All rights reserved.
|
||||
//
|
||||
// This program 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
|
||||
// any later version.
|
||||
//
|
||||
// This program 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 should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>
|
||||
//
|
||||
|
||||
import UIKit
|
||||
|
||||
protocol AppleWatchFlowControllerParent: AnyObject {
|
||||
func toBackup()
|
||||
}
|
||||
|
||||
protocol AppleWatchFlowControlling: AnyObject {
|
||||
func toSystemWatchApp()
|
||||
func toBackup()
|
||||
}
|
||||
|
||||
final class AppleWatchFlowController: FlowController {
|
||||
private weak var parent: AppleWatchFlowControllerParent?
|
||||
private weak var navigationController: UINavigationController?
|
||||
|
||||
static func push(
|
||||
in navigationController: UINavigationController,
|
||||
parent: AppleWatchFlowControllerParent
|
||||
) {
|
||||
let viewController = AppleWatchViewController()
|
||||
let flowController = AppleWatchFlowController(viewController: viewController)
|
||||
flowController.parent = parent
|
||||
flowController.navigationController = navigationController
|
||||
let presenter = AppleWatchPresenter(flowController: flowController)
|
||||
viewController.presenter = presenter
|
||||
|
||||
navigationController.pushRootViewController(viewController, animated: true)
|
||||
}
|
||||
}
|
||||
|
||||
extension AppleWatchFlowController: AppleWatchFlowControlling {
|
||||
func toSystemWatchApp() {
|
||||
if let url = URL(string: "itms-watchs://") {
|
||||
UIApplication.shared.open(url, options: [:], completionHandler: nil)
|
||||
}
|
||||
}
|
||||
|
||||
func toBackup() {
|
||||
parent?.toBackup()
|
||||
}
|
||||
}
|
@ -0,0 +1,49 @@
|
||||
//
|
||||
// This file is part of the 2FAS iOS app (https://github.com/twofas/2fas-ios)
|
||||
// Copyright © 2024 Two Factor Authentication Service, Inc.
|
||||
// Contributed by Grzegorz Machnio. All rights reserved.
|
||||
//
|
||||
// This program 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
|
||||
// any later version.
|
||||
//
|
||||
// This program 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 should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
protocol AppleWatchPresenting {
|
||||
var appleWatchInstallationSteps: [AppleWatchInstallationStep] { get }
|
||||
|
||||
func handleInstallationStep(number: Int)
|
||||
}
|
||||
|
||||
final class AppleWatchPresenter: AppleWatchPresenting {
|
||||
let appleWatchInstallationSteps: [AppleWatchInstallationStep] = [
|
||||
.init(description: T.AppleWatch.installationFirstStep,
|
||||
actionTitle: T.AppleWatch.installationFirstStepLink),
|
||||
.init(description: T.AppleWatch.installationSecondStep,
|
||||
actionTitle: T.AppleWatch.installationSecondStepLink)
|
||||
]
|
||||
|
||||
private let flowController: AppleWatchFlowControlling
|
||||
|
||||
init(flowController: AppleWatchFlowControlling) {
|
||||
self.flowController = flowController
|
||||
}
|
||||
|
||||
func handleInstallationStep(number: Int) {
|
||||
if number == 1 {
|
||||
flowController.toSystemWatchApp()
|
||||
} else if number == 2 {
|
||||
flowController.toBackup()
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,114 @@
|
||||
//
|
||||
// This file is part of the 2FAS iOS app (https://github.com/twofas/2fas-ios)
|
||||
// Copyright © 2024 Two Factor Authentication Service, Inc.
|
||||
// Contributed by Grzegorz Machnio. All rights reserved.
|
||||
//
|
||||
// This program 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
|
||||
// any later version.
|
||||
//
|
||||
// This program 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 should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>
|
||||
//
|
||||
|
||||
import SwiftUI
|
||||
import Common
|
||||
|
||||
struct AppleWatchInstallationStep: Hashable, Identifiable {
|
||||
var id = UUID()
|
||||
let description: String
|
||||
let actionTitle: String
|
||||
}
|
||||
|
||||
struct AppleWatchView<Presenter: AppleWatchPresenting>: View {
|
||||
private let spacing: CGFloat = Theme.Metrics.doubleSpacing
|
||||
private let presenter: Presenter
|
||||
|
||||
init(presenter: Presenter) {
|
||||
self.presenter = presenter
|
||||
}
|
||||
|
||||
var body: some View {
|
||||
VStack(spacing: spacing) {
|
||||
Image(uiImage: Asset.appleWatch.image)
|
||||
.renderingMode(.original)
|
||||
.padding(.top, Theme.Metrics.standardSpacing)
|
||||
|
||||
Text(T.AppleWatch.installationInfoTitle)
|
||||
.font(Font(Theme.Fonts.Text.title))
|
||||
.multilineTextAlignment(.center)
|
||||
.minimumScaleFactor(0.7)
|
||||
|
||||
VStack(alignment: .leading) {
|
||||
ForEach(Array(presenter.appleWatchInstallationSteps.enumerated()), id: \.element) { index, step in
|
||||
let stepNumber = index + 1
|
||||
stepView(
|
||||
for: step,
|
||||
stepNumber: stepNumber,
|
||||
isDividerVisible: stepNumber != presenter.appleWatchInstallationSteps.count
|
||||
)
|
||||
}
|
||||
}
|
||||
.padding(.horizontal, Theme.Metrics.quadrupleMargin)
|
||||
}
|
||||
}
|
||||
|
||||
private func stepView(
|
||||
for step: AppleWatchInstallationStep,
|
||||
stepNumber: Int,
|
||||
isDividerVisible: Bool
|
||||
) -> some View {
|
||||
HStack(alignment: .top) {
|
||||
Text("\(stepNumber)")
|
||||
.font(Font(Theme.Fonts.iconLabelLarge))
|
||||
.frame(width: 28, height: 28)
|
||||
.background(Color(Theme.Colors.Fill.tertiary))
|
||||
.clipShape(Circle())
|
||||
|
||||
VStack(alignment: .leading, spacing: Theme.Metrics.halfSpacing) {
|
||||
Text(step.description)
|
||||
.font(Font(Theme.Fonts.Text.content))
|
||||
|
||||
Button {
|
||||
presenter.handleInstallationStep(number: stepNumber)
|
||||
} label: {
|
||||
HStack(spacing: Theme.Metrics.halfSpacing) {
|
||||
Text(step.actionTitle)
|
||||
.font(Font(Theme.Fonts.Text.boldContent))
|
||||
|
||||
Image(systemName: "arrow.up.right")
|
||||
.font(Font(Theme.Fonts.iconLabelExtraLarge))
|
||||
}
|
||||
.foregroundColor(Color(Theme.Colors.Text.theme))
|
||||
}
|
||||
|
||||
if isDividerVisible {
|
||||
Divider()
|
||||
.frame(height: Theme.Metrics.separatorHeight)
|
||||
.padding(.vertical, Theme.Metrics.standardSpacing)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#Preview {
|
||||
final class AppleWatchPresenterMock: AppleWatchPresenting {
|
||||
let appleWatchInstallationSteps: [AppleWatchInstallationStep] = [
|
||||
.init(description: T.AppleWatch.installationFirstStep,
|
||||
actionTitle: T.AppleWatch.installationFirstStepLink),
|
||||
.init(description: T.AppleWatch.installationSecondStep,
|
||||
actionTitle: T.AppleWatch.installationSecondStepLink)
|
||||
]
|
||||
|
||||
func handleInstallationStep(number: Int) {}
|
||||
}
|
||||
|
||||
return AppleWatchView(presenter: AppleWatchPresenterMock())
|
||||
}
|
@ -0,0 +1,38 @@
|
||||
//
|
||||
// This file is part of the 2FAS iOS app (https://github.com/twofas/2fas-ios)
|
||||
// Copyright © 2024 Two Factor Authentication Service, Inc.
|
||||
// Contributed by Grzegorz Machnio. All rights reserved.
|
||||
//
|
||||
// This program 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
|
||||
// any later version.
|
||||
//
|
||||
// This program 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 should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>
|
||||
//
|
||||
|
||||
import UIKit
|
||||
import SwiftUI
|
||||
|
||||
final class AppleWatchViewController: UIViewController {
|
||||
var presenter: AppleWatchPresenter!
|
||||
|
||||
override func viewDidLoad() {
|
||||
title = T.Settings.appleWatch
|
||||
|
||||
let appleWatchView = AppleWatchView(presenter: presenter)
|
||||
let hostingController = UIHostingController(rootView: appleWatchView)
|
||||
hostingController.willMove(toParent: self)
|
||||
addChild(hostingController)
|
||||
view.addSubview(hostingController.view)
|
||||
hostingController.view.pinToParent()
|
||||
hostingController.didMove(toParent: self)
|
||||
}
|
||||
|
||||
}
|
@ -45,6 +45,7 @@ protocol SettingsMenuFlowControllerParent: AnyObject {
|
||||
func toUpdateCurrentPosition(_ viewPath: ViewPath.Settings?)
|
||||
func toExternalImport()
|
||||
func toAppearance()
|
||||
func toAppleWatch()
|
||||
}
|
||||
|
||||
protocol SettingsMenuFlowControlling: AnyObject {
|
||||
@ -60,6 +61,7 @@ protocol SettingsMenuFlowControlling: AnyObject {
|
||||
func toUpdateCurrentPosition(_ viewPath: ViewPath.Settings?)
|
||||
func toExternalImport()
|
||||
func toAppearance()
|
||||
func toAppleWatch()
|
||||
}
|
||||
|
||||
final class SettingsMenuFlowController: FlowController {
|
||||
@ -109,6 +111,7 @@ extension SettingsMenuFlowController: SettingsMenuFlowControlling {
|
||||
func toUpdateCurrentPosition(_ viewPath: ViewPath.Settings?) { parent?.toUpdateCurrentPosition(viewPath) }
|
||||
func toExternalImport() { parent?.toExternalImport() }
|
||||
func toAppearance() { parent?.toAppearance() }
|
||||
func toAppleWatch() { parent?.toAppleWatch() }
|
||||
}
|
||||
|
||||
extension SettingsMenuFlowController: SettingsMenuFlowControllerChild {
|
||||
|
@ -78,6 +78,7 @@ enum SettingsNavigationModule: Hashable {
|
||||
case donate
|
||||
case externalImport
|
||||
case appearance
|
||||
case appleWatch
|
||||
}
|
||||
|
||||
enum SettingsNavigationToggle: Hashable {
|
||||
|
@ -64,7 +64,7 @@ extension SettingsMenuPresenter {
|
||||
return T.Commons.off
|
||||
}()
|
||||
let browerExtension = SettingsMenuSection(
|
||||
title: T.Browser.browserExtension,
|
||||
title: T.Settings.advanced,
|
||||
cells: [
|
||||
.init(
|
||||
icon: Asset.settingsBrowserExtension.image,
|
||||
@ -72,6 +72,12 @@ extension SettingsMenuPresenter {
|
||||
info: browerExtensionDescription,
|
||||
accessory: .arrow,
|
||||
action: .navigation(navigatesTo: .browserExtension)
|
||||
),
|
||||
.init(
|
||||
icon: Asset.settingsWatch.image,
|
||||
title: T.Settings.appleWatch,
|
||||
accessory: .arrow,
|
||||
action: .navigation(navigatesTo: .appleWatch)
|
||||
)
|
||||
]
|
||||
)
|
||||
|
@ -201,6 +201,8 @@ private extension SettingsMenuPresenter {
|
||||
flowController.toExternalImport()
|
||||
case .appearance:
|
||||
flowController.toAppearance()
|
||||
case .appleWatch:
|
||||
flowController.toAppleWatch()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -214,6 +214,10 @@ extension SettingsFlowController: SettingsMenuFlowControllerParent {
|
||||
AppearanceFlowController.showAsRoot(in: viewController.contentNavi, parent: self)
|
||||
}
|
||||
}
|
||||
|
||||
func toAppleWatch() {
|
||||
AppleWatchFlowController.push(in: viewController.navigationNavi, parent: self)
|
||||
}
|
||||
}
|
||||
extension SettingsFlowController: BackupMenuFlowControllerParent {
|
||||
func showFAQ() {
|
||||
@ -239,3 +243,4 @@ extension SettingsFlowController: BrowserExtensionMainFlowControllerParent {}
|
||||
extension SettingsFlowController: AboutFlowControllerParent {}
|
||||
extension SettingsFlowController: ExternalImportFlowControllerParent {}
|
||||
extension SettingsFlowController: AppearanceFlowControllerParent {}
|
||||
extension SettingsFlowController: AppleWatchFlowControllerParent {}
|
||||
|
@ -289,6 +289,18 @@ internal enum T {
|
||||
/// Active search
|
||||
internal static let toggleActiveSearch = T.tr("Localizable", "appearance__toggle_active_search", fallback: "Active search")
|
||||
}
|
||||
internal enum AppleWatch {
|
||||
/// Install 2FAS Auth via Watch app
|
||||
internal static let installationFirstStep = T.tr("Localizable", "appleWatch__installation_first_step", fallback: "Install 2FAS Auth via Watch app")
|
||||
/// Open Watch app
|
||||
internal static let installationFirstStepLink = T.tr("Localizable", "appleWatch__installation_first_step_link", fallback: "Open Watch app")
|
||||
/// 2FAS Apple Watch app installation
|
||||
internal static let installationInfoTitle = T.tr("Localizable", "appleWatch__installation_info_title", fallback: "2FAS Apple Watch app installation")
|
||||
/// Ensure your iCloud Sync is enabled
|
||||
internal static let installationSecondStep = T.tr("Localizable", "appleWatch__installation_second_step", fallback: "Ensure your iCloud Sync is enabled")
|
||||
/// Go to 2FAS Backup settings
|
||||
internal static let installationSecondStepLink = T.tr("Localizable", "appleWatch__installation_second_step_link", fallback: "Go to 2FAS Backup settings")
|
||||
}
|
||||
internal enum Backup {
|
||||
/// 2FAS Backup
|
||||
internal static let _2fasBackup = T.tr("Localizable", "backup__2fas_backup", fallback: "2FAS Backup")
|
||||
@ -378,9 +390,9 @@ internal enum T {
|
||||
internal static let incorrectCharacterError = T.tr("Localizable", "backup__incorrect_character_error", fallback: "Incorrect character. Use only letter A-Z, a-z, digits and special characters: -_/!#$%&+*~@?=^.,'(){}[]:;<>|")
|
||||
/// Incorrect Password
|
||||
internal static let incorrectPassword = T.tr("Localizable", "backup__incorrect_password", fallback: "Incorrect Password")
|
||||
/// Couldn't backup tokens because "%@" secret contains illegal characters. Remove it from list and try again
|
||||
/// Couldn't backup tokens because "%@" secret contains invalid characters. Remove it from list and try again
|
||||
internal static func incorrectSecret(_ p1: Any) -> String {
|
||||
return T.tr("Localizable", "backup__incorrect_secret", String(describing: p1), fallback: "Couldn't backup tokens because \"%@\" secret contains illegal characters. Remove it from list and try again")
|
||||
return T.tr("Localizable", "backup__incorrect_secret", String(describing: p1), fallback: "Couldn't backup tokens because \"%@\" secret contains invalid characters. Remove it from list and try again")
|
||||
}
|
||||
/// Local file
|
||||
internal static let localFileTitle = T.tr("Localizable", "backup__local_file_title", fallback: "Local file")
|
||||
@ -1020,6 +1032,8 @@ internal enum T {
|
||||
internal static let appSecurity = T.tr("Localizable", "settings__app_security", fallback: "App security")
|
||||
/// Appearance
|
||||
internal static let appearance = T.tr("Localizable", "settings__appearance", fallback: "Appearance")
|
||||
/// Apple Watch
|
||||
internal static let appleWatch = T.tr("Localizable", "settings__apple_watch", fallback: "Apple Watch")
|
||||
/// Backup and Synchronization
|
||||
internal static let backupAndSynchronization = T.tr("Localizable", "settings__backup_and_synchronization", fallback: "Backup and Synchronization")
|
||||
/// Biometric Authentication
|
||||
|
Loading…
Reference in New Issue
Block a user