Implemented SwiftUI FlickerCodeTanView; extracted ScaleImageView from ImageTanView
This commit is contained in:
parent
b3dd944ce5
commit
b28f6ae68f
|
@ -1,5 +1,6 @@
|
||||||
package net.dankito.banking.ui.util
|
package net.dankito.banking.ui.util
|
||||||
|
|
||||||
|
import net.dankito.utils.multiplatform.Freezer
|
||||||
import net.dankito.utils.multiplatform.ObjectHolder
|
import net.dankito.utils.multiplatform.ObjectHolder
|
||||||
|
|
||||||
|
|
||||||
|
@ -56,7 +57,7 @@ open class FlickerCodeStepsCalculator {
|
||||||
steps.add(calculateStep(halfbyteid, clock, bitarray))
|
steps.add(calculateStep(halfbyteid, clock, bitarray))
|
||||||
} while (halfbyteid.value > 0 || clock.value == Bit.Low)
|
} while (halfbyteid.value > 0 || clock.value == Bit.Low)
|
||||||
|
|
||||||
return steps
|
return Freezer.freeze(steps)
|
||||||
}
|
}
|
||||||
|
|
||||||
protected open fun calculateStep(halfbyteid: ObjectHolder<Int>, clock: ObjectHolder<Bit>, bitarray: List<Step>): Step {
|
protected open fun calculateStep(halfbyteid: ObjectHolder<Int>, clock: ObjectHolder<Bit>, bitarray: List<Step>): Step {
|
||||||
|
|
|
@ -9,6 +9,16 @@
|
||||||
/* Begin PBXBuildFile section */
|
/* Begin PBXBuildFile section */
|
||||||
3607829924E148D40098FEFE /* AdaptsToKeyboard.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3607829824E148D40098FEFE /* AdaptsToKeyboard.swift */; };
|
3607829924E148D40098FEFE /* AdaptsToKeyboard.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3607829824E148D40098FEFE /* AdaptsToKeyboard.swift */; };
|
||||||
360782C124E18D5E0098FEFE /* AddAccountButtonView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 360782C024E18D5E0098FEFE /* AddAccountButtonView.swift */; };
|
360782C124E18D5E0098FEFE /* AddAccountButtonView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 360782C024E18D5E0098FEFE /* AddAccountButtonView.swift */; };
|
||||||
|
360782C324E49FF70098FEFE /* ValidationLabel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 360782C224E49FF70098FEFE /* ValidationLabel.swift */; };
|
||||||
|
360782C524E541970098FEFE /* ScaleImageView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 360782C424E541970098FEFE /* ScaleImageView.swift */; };
|
||||||
|
360782C724E544170098FEFE /* FlickerCodeTanView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 360782C624E544170098FEFE /* FlickerCodeTanView.swift */; };
|
||||||
|
360782CB24E5746B0098FEFE /* FlickerCodeAnimator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 360782CA24E5746A0098FEFE /* FlickerCodeAnimator.swift */; };
|
||||||
|
360782CD24F1A57F0098FEFE /* LabelledUIKitTextFieldWithValidationLabel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 360782CC24F1A57E0098FEFE /* LabelledUIKitTextFieldWithValidationLabel.swift */; };
|
||||||
|
360782CF24F3D6610098FEFE /* InfoLabel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 360782CE24F3D6610098FEFE /* InfoLabel.swift */; };
|
||||||
|
360782D124F3F4120098FEFE /* SelectorWrapper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 360782D024F3F4120098FEFE /* SelectorWrapper.swift */; };
|
||||||
|
360782D324F429F80098FEFE /* FlickerCodeStripe.swift in Sources */ = {isa = PBXBuildFile; fileRef = 360782D224F429F70098FEFE /* FlickerCodeStripe.swift */; };
|
||||||
|
3608D6C224FBA9C6006C93A8 /* TrianglePointingDown.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3608D6C124FBA9C6006C93A8 /* TrianglePointingDown.swift */; };
|
||||||
|
3608D6C624FBAB41006C93A8 /* TanGeneratorPositionMarker.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3608D6C524FBAB41006C93A8 /* TanGeneratorPositionMarker.swift */; };
|
||||||
366FA4DA24C472A90094F009 /* Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 366FA4D924C472A90094F009 /* Extensions.swift */; };
|
366FA4DA24C472A90094F009 /* Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 366FA4D924C472A90094F009 /* Extensions.swift */; };
|
||||||
366FA4DC24C479120094F009 /* BankInfoListItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 366FA4DB24C479120094F009 /* BankInfoListItem.swift */; };
|
366FA4DC24C479120094F009 /* BankInfoListItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 366FA4DB24C479120094F009 /* BankInfoListItem.swift */; };
|
||||||
366FA4E024C4924A0094F009 /* RemitteeListItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 366FA4DF24C4924A0094F009 /* RemitteeListItem.swift */; };
|
366FA4E024C4924A0094F009 /* RemitteeListItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 366FA4DF24C4924A0094F009 /* RemitteeListItem.swift */; };
|
||||||
|
@ -128,6 +138,16 @@
|
||||||
/* Begin PBXFileReference section */
|
/* Begin PBXFileReference section */
|
||||||
3607829824E148D40098FEFE /* AdaptsToKeyboard.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AdaptsToKeyboard.swift; sourceTree = "<group>"; };
|
3607829824E148D40098FEFE /* AdaptsToKeyboard.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AdaptsToKeyboard.swift; sourceTree = "<group>"; };
|
||||||
360782C024E18D5E0098FEFE /* AddAccountButtonView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AddAccountButtonView.swift; sourceTree = "<group>"; };
|
360782C024E18D5E0098FEFE /* AddAccountButtonView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AddAccountButtonView.swift; sourceTree = "<group>"; };
|
||||||
|
360782C224E49FF70098FEFE /* ValidationLabel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ValidationLabel.swift; sourceTree = "<group>"; };
|
||||||
|
360782C424E541970098FEFE /* ScaleImageView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ScaleImageView.swift; sourceTree = "<group>"; };
|
||||||
|
360782C624E544170098FEFE /* FlickerCodeTanView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FlickerCodeTanView.swift; sourceTree = "<group>"; };
|
||||||
|
360782CA24E5746A0098FEFE /* FlickerCodeAnimator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FlickerCodeAnimator.swift; sourceTree = "<group>"; };
|
||||||
|
360782CC24F1A57E0098FEFE /* LabelledUIKitTextFieldWithValidationLabel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LabelledUIKitTextFieldWithValidationLabel.swift; sourceTree = "<group>"; };
|
||||||
|
360782CE24F3D6610098FEFE /* InfoLabel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InfoLabel.swift; sourceTree = "<group>"; };
|
||||||
|
360782D024F3F4120098FEFE /* SelectorWrapper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SelectorWrapper.swift; sourceTree = "<group>"; };
|
||||||
|
360782D224F429F70098FEFE /* FlickerCodeStripe.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FlickerCodeStripe.swift; sourceTree = "<group>"; };
|
||||||
|
3608D6C124FBA9C6006C93A8 /* TrianglePointingDown.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TrianglePointingDown.swift; sourceTree = "<group>"; };
|
||||||
|
3608D6C524FBAB41006C93A8 /* TanGeneratorPositionMarker.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TanGeneratorPositionMarker.swift; sourceTree = "<group>"; };
|
||||||
366FA4D924C472A90094F009 /* Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Extensions.swift; sourceTree = "<group>"; };
|
366FA4D924C472A90094F009 /* Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Extensions.swift; sourceTree = "<group>"; };
|
||||||
366FA4DB24C479120094F009 /* BankInfoListItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BankInfoListItem.swift; sourceTree = "<group>"; };
|
366FA4DB24C479120094F009 /* BankInfoListItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BankInfoListItem.swift; sourceTree = "<group>"; };
|
||||||
366FA4DF24C4924A0094F009 /* RemitteeListItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RemitteeListItem.swift; sourceTree = "<group>"; };
|
366FA4DF24C4924A0094F009 /* RemitteeListItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RemitteeListItem.swift; sourceTree = "<group>"; };
|
||||||
|
@ -403,8 +423,13 @@
|
||||||
36BE06B424CF85A300CBBB68 /* AmountLabel.swift */,
|
36BE06B424CF85A300CBBB68 /* AmountLabel.swift */,
|
||||||
36BE06C724D0DE7400CBBB68 /* UIKitTextField.swift */,
|
36BE06C724D0DE7400CBBB68 /* UIKitTextField.swift */,
|
||||||
36E21EDA24DC990300649DC8 /* LabelledUIKitTextField.swift */,
|
36E21EDA24DC990300649DC8 /* LabelledUIKitTextField.swift */,
|
||||||
|
360782CE24F3D6610098FEFE /* InfoLabel.swift */,
|
||||||
|
360782C224E49FF70098FEFE /* ValidationLabel.swift */,
|
||||||
|
360782CC24F1A57E0098FEFE /* LabelledUIKitTextFieldWithValidationLabel.swift */,
|
||||||
36E21EDC24DCA89100649DC8 /* TanProcedurePicker.swift */,
|
36E21EDC24DCA89100649DC8 /* TanProcedurePicker.swift */,
|
||||||
3607829824E148D40098FEFE /* AdaptsToKeyboard.swift */,
|
3607829824E148D40098FEFE /* AdaptsToKeyboard.swift */,
|
||||||
|
360782CA24E5746A0098FEFE /* FlickerCodeAnimator.swift */,
|
||||||
|
360782D024F3F4120098FEFE /* SelectorWrapper.swift */,
|
||||||
);
|
);
|
||||||
path = ui;
|
path = ui;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
|
@ -424,7 +449,10 @@
|
||||||
366FA4DB24C479120094F009 /* BankInfoListItem.swift */,
|
366FA4DB24C479120094F009 /* BankInfoListItem.swift */,
|
||||||
366FA4DF24C4924A0094F009 /* RemitteeListItem.swift */,
|
366FA4DF24C4924A0094F009 /* RemitteeListItem.swift */,
|
||||||
366FA4E124C4ED6C0094F009 /* EnterTanDialog.swift */,
|
366FA4E124C4ED6C0094F009 /* EnterTanDialog.swift */,
|
||||||
|
360782C424E541970098FEFE /* ScaleImageView.swift */,
|
||||||
36BE064E24C9A17F00CBBB68 /* ImageTanView.swift */,
|
36BE064E24C9A17F00CBBB68 /* ImageTanView.swift */,
|
||||||
|
360782C624E544170098FEFE /* FlickerCodeTanView.swift */,
|
||||||
|
360782D224F429F70098FEFE /* FlickerCodeStripe.swift */,
|
||||||
36E21ED024DC540400649DC8 /* SettingsDialog.swift */,
|
36E21ED024DC540400649DC8 /* SettingsDialog.swift */,
|
||||||
36E21ED424DC549800649DC8 /* BankSettingsDialog.swift */,
|
36E21ED424DC549800649DC8 /* BankSettingsDialog.swift */,
|
||||||
36E21ED624DC617200649DC8 /* BankAccountSettingsDialog.swift */,
|
36E21ED624DC617200649DC8 /* BankAccountSettingsDialog.swift */,
|
||||||
|
@ -435,6 +463,8 @@
|
||||||
36C4009A24D2F9E4005227AD /* IconedTitleView.swift */,
|
36C4009A24D2F9E4005227AD /* IconedTitleView.swift */,
|
||||||
36E21ECE24DA0EEE00649DC8 /* IconView.swift */,
|
36E21ECE24DA0EEE00649DC8 /* IconView.swift */,
|
||||||
36E21EDE24DCCC2700649DC8 /* CheckmarkListItem.swift */,
|
36E21EDE24DCCC2700649DC8 /* CheckmarkListItem.swift */,
|
||||||
|
3608D6C124FBA9C6006C93A8 /* TrianglePointingDown.swift */,
|
||||||
|
3608D6C524FBAB41006C93A8 /* TanGeneratorPositionMarker.swift */,
|
||||||
);
|
);
|
||||||
path = views;
|
path = views;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
|
@ -607,6 +637,7 @@
|
||||||
36E21EDB24DC990300649DC8 /* LabelledUIKitTextField.swift in Sources */,
|
36E21EDB24DC990300649DC8 /* LabelledUIKitTextField.swift in Sources */,
|
||||||
36BE068D24CE41E700CBBB68 /* Styles.swift in Sources */,
|
36BE068D24CE41E700CBBB68 /* Styles.swift in Sources */,
|
||||||
36E21ECB24D88DF000649DC8 /* UIKitExtensions.swift in Sources */,
|
36E21ECB24D88DF000649DC8 /* UIKitExtensions.swift in Sources */,
|
||||||
|
360782C524E541970098FEFE /* ScaleImageView.swift in Sources */,
|
||||||
366FA4E224C4ED6C0094F009 /* EnterTanDialog.swift in Sources */,
|
366FA4E224C4ED6C0094F009 /* EnterTanDialog.swift in Sources */,
|
||||||
36FC92DC24B3A4A0002B12E9 /* AccountsTab.swift in Sources */,
|
36FC92DC24B3A4A0002B12E9 /* AccountsTab.swift in Sources */,
|
||||||
36BCF86E24BA691B005BEC29 /* DependencyInjector.swift in Sources */,
|
36BCF86E24BA691B005BEC29 /* DependencyInjector.swift in Sources */,
|
||||||
|
@ -614,24 +645,31 @@
|
||||||
36BE06B824D077EC00CBBB68 /* SwiftBankIconFinder.swift in Sources */,
|
36BE06B824D077EC00CBBB68 /* SwiftBankIconFinder.swift in Sources */,
|
||||||
36BCF89124C25971005BEC29 /* CoreDataBankingPersistence.swift in Sources */,
|
36BCF89124C25971005BEC29 /* CoreDataBankingPersistence.swift in Sources */,
|
||||||
36FC92A124B39A05002B12E9 /* BankingiOSApp.xcdatamodeld in Sources */,
|
36FC92A124B39A05002B12E9 /* BankingiOSApp.xcdatamodeld in Sources */,
|
||||||
|
360782D324F429F80098FEFE /* FlickerCodeStripe.swift in Sources */,
|
||||||
36BE06C624D080C900CBBB68 /* FaviconType.swift in Sources */,
|
36BE06C624D080C900CBBB68 /* FaviconType.swift in Sources */,
|
||||||
|
360782CD24F1A57F0098FEFE /* LabelledUIKitTextFieldWithValidationLabel.swift in Sources */,
|
||||||
36BCF89324C25BC3005BEC29 /* Mapper.swift in Sources */,
|
36BCF89324C25BC3005BEC29 /* Mapper.swift in Sources */,
|
||||||
36FC92D724B3A3BA002B12E9 /* NSUrlWebClient.swift in Sources */,
|
36FC92D724B3A3BA002B12E9 /* NSUrlWebClient.swift in Sources */,
|
||||||
|
360782D124F3F4120098FEFE /* SelectorWrapper.swift in Sources */,
|
||||||
36BE06B324CF133400CBBB68 /* JsonEncoderSerializer.swift in Sources */,
|
36BE06B324CF133400CBBB68 /* JsonEncoderSerializer.swift in Sources */,
|
||||||
36BE06BA24D0783900CBBB68 /* FaviconFinder.swift in Sources */,
|
36BE06BA24D0783900CBBB68 /* FaviconFinder.swift in Sources */,
|
||||||
36BCF89524C31F02005BEC29 /* AppData.swift in Sources */,
|
36BCF89524C31F02005BEC29 /* AppData.swift in Sources */,
|
||||||
36E21EDD24DCA89100649DC8 /* TanProcedurePicker.swift in Sources */,
|
36E21EDD24DCA89100649DC8 /* TanProcedurePicker.swift in Sources */,
|
||||||
|
3608D6C624FBAB41006C93A8 /* TanGeneratorPositionMarker.swift in Sources */,
|
||||||
36BE065B24CA4B3500CBBB68 /* SelectBankDialog.swift in Sources */,
|
36BE065B24CA4B3500CBBB68 /* SelectBankDialog.swift in Sources */,
|
||||||
36E21ED524DC549800649DC8 /* BankSettingsDialog.swift in Sources */,
|
36E21ED524DC549800649DC8 /* BankSettingsDialog.swift in Sources */,
|
||||||
36BE068924CE288800CBBB68 /* CollapsibleText.swift in Sources */,
|
36BE068924CE288800CBBB68 /* CollapsibleText.swift in Sources */,
|
||||||
36BE06B524CF85A300CBBB68 /* AmountLabel.swift in Sources */,
|
36BE06B524CF85A300CBBB68 /* AmountLabel.swift in Sources */,
|
||||||
36BCF88324C098BB005BEC29 /* BankListItem.swift in Sources */,
|
36BCF88324C098BB005BEC29 /* BankListItem.swift in Sources */,
|
||||||
|
360782CB24E5746B0098FEFE /* FlickerCodeAnimator.swift in Sources */,
|
||||||
36BCF88D24C1C1EA005BEC29 /* TransferMoneyDialog.swift in Sources */,
|
36BCF88D24C1C1EA005BEC29 /* TransferMoneyDialog.swift in Sources */,
|
||||||
36E21EDF24DCCC2700649DC8 /* CheckmarkListItem.swift in Sources */,
|
36E21EDF24DCCC2700649DC8 /* CheckmarkListItem.swift in Sources */,
|
||||||
36E7BA1424B3D05C00757859 /* ViewExtensions.swift in Sources */,
|
36E7BA1424B3D05C00757859 /* ViewExtensions.swift in Sources */,
|
||||||
36BCF88924C0A7D7005BEC29 /* Message.swift in Sources */,
|
36BCF88924C0A7D7005BEC29 /* Message.swift in Sources */,
|
||||||
366FA4E024C4924A0094F009 /* RemitteeListItem.swift in Sources */,
|
366FA4E024C4924A0094F009 /* RemitteeListItem.swift in Sources */,
|
||||||
|
3608D6C224FBA9C6006C93A8 /* TrianglePointingDown.swift in Sources */,
|
||||||
36BE068B24CE3B0400CBBB68 /* SwiftExtensions.swift in Sources */,
|
36BE068B24CE3B0400CBBB68 /* SwiftExtensions.swift in Sources */,
|
||||||
|
360782C724E544170098FEFE /* FlickerCodeTanView.swift in Sources */,
|
||||||
36BE065D24CB08FC00CBBB68 /* LazyView.swift in Sources */,
|
36BE065D24CB08FC00CBBB68 /* LazyView.swift in Sources */,
|
||||||
360782C124E18D5E0098FEFE /* AddAccountButtonView.swift in Sources */,
|
360782C124E18D5E0098FEFE /* AddAccountButtonView.swift in Sources */,
|
||||||
36BCF86C24BA5E72005BEC29 /* DispatchQueueAsyncRunner.swift in Sources */,
|
36BCF86C24BA5E72005BEC29 /* DispatchQueueAsyncRunner.swift in Sources */,
|
||||||
|
@ -642,12 +680,14 @@
|
||||||
36BE06C424D0801A00CBBB68 /* Size.swift in Sources */,
|
36BE06C424D0801A00CBBB68 /* Size.swift in Sources */,
|
||||||
36FC92A324B39A05002B12E9 /* ContentView.swift in Sources */,
|
36FC92A324B39A05002B12E9 /* ContentView.swift in Sources */,
|
||||||
366FA4E624C6EBF40094F009 /* EnterTanState.swift in Sources */,
|
366FA4E624C6EBF40094F009 /* EnterTanState.swift in Sources */,
|
||||||
|
360782CF24F3D6610098FEFE /* InfoLabel.swift in Sources */,
|
||||||
36C4009B24D2F9E4005227AD /* IconedTitleView.swift in Sources */,
|
36C4009B24D2F9E4005227AD /* IconedTitleView.swift in Sources */,
|
||||||
36BE065724C9E04800CBBB68 /* UIKitImageView.swift in Sources */,
|
36BE065724C9E04800CBBB68 /* UIKitImageView.swift in Sources */,
|
||||||
36BCF88724C0A310005BEC29 /* PreviewData.swift in Sources */,
|
36BCF88724C0A310005BEC29 /* PreviewData.swift in Sources */,
|
||||||
36E21ED724DC617200649DC8 /* BankAccountSettingsDialog.swift in Sources */,
|
36E21ED724DC617200649DC8 /* BankAccountSettingsDialog.swift in Sources */,
|
||||||
366FA4DA24C472A90094F009 /* Extensions.swift in Sources */,
|
366FA4DA24C472A90094F009 /* Extensions.swift in Sources */,
|
||||||
36BE068F24CEE1BD00CBBB68 /* AllBanksListItem.swift in Sources */,
|
36BE068F24CEE1BD00CBBB68 /* AllBanksListItem.swift in Sources */,
|
||||||
|
360782C324E49FF70098FEFE /* ValidationLabel.swift in Sources */,
|
||||||
36BE069124CEF52800CBBB68 /* UpdateButton.swift in Sources */,
|
36BE069124CEF52800CBBB68 /* UpdateButton.swift in Sources */,
|
||||||
36E21ED124DC540400649DC8 /* SettingsDialog.swift in Sources */,
|
36E21ED124DC540400649DC8 /* SettingsDialog.swift in Sources */,
|
||||||
366FA4DC24C479120094F009 /* BankInfoListItem.swift in Sources */,
|
366FA4DC24C479120094F009 /* BankInfoListItem.swift in Sources */,
|
||||||
|
@ -767,7 +807,7 @@
|
||||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||||
IPHONEOS_DEPLOYMENT_TARGET = 13.5;
|
IPHONEOS_DEPLOYMENT_TARGET = 13.6;
|
||||||
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
|
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
|
||||||
MTL_FAST_MATH = YES;
|
MTL_FAST_MATH = YES;
|
||||||
ONLY_ACTIVE_ARCH = YES;
|
ONLY_ACTIVE_ARCH = YES;
|
||||||
|
@ -822,7 +862,7 @@
|
||||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||||
IPHONEOS_DEPLOYMENT_TARGET = 13.5;
|
IPHONEOS_DEPLOYMENT_TARGET = 13.6;
|
||||||
MTL_ENABLE_DEBUG_INFO = NO;
|
MTL_ENABLE_DEBUG_INFO = NO;
|
||||||
MTL_FAST_MATH = YES;
|
MTL_FAST_MATH = YES;
|
||||||
SDKROOT = iphoneos;
|
SDKROOT = iphoneos;
|
||||||
|
@ -849,6 +889,7 @@
|
||||||
"../../ui/BankingUiNativeIntegration/build/xcode-frameworks/",
|
"../../ui/BankingUiNativeIntegration/build/xcode-frameworks/",
|
||||||
);
|
);
|
||||||
INFOPLIST_FILE = BankingiOSApp/Info.plist;
|
INFOPLIST_FILE = BankingiOSApp/Info.plist;
|
||||||
|
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
|
||||||
LD_RUNPATH_SEARCH_PATHS = (
|
LD_RUNPATH_SEARCH_PATHS = (
|
||||||
"$(inherited)",
|
"$(inherited)",
|
||||||
"@executable_path/Frameworks",
|
"@executable_path/Frameworks",
|
||||||
|
@ -857,7 +898,7 @@
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = net.dankito.banking.ios.BankingiOSApp.freeprovisioning;
|
PRODUCT_BUNDLE_IDENTIFIER = net.dankito.banking.ios.BankingiOSApp.freeprovisioning;
|
||||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
SWIFT_VERSION = 5.0;
|
SWIFT_VERSION = 5.0;
|
||||||
TARGETED_DEVICE_FAMILY = 1;
|
TARGETED_DEVICE_FAMILY = "1,2";
|
||||||
};
|
};
|
||||||
name = Debug;
|
name = Debug;
|
||||||
};
|
};
|
||||||
|
@ -878,6 +919,7 @@
|
||||||
"../../ui/BankingUiNativeIntegration/build/xcode-frameworks/",
|
"../../ui/BankingUiNativeIntegration/build/xcode-frameworks/",
|
||||||
);
|
);
|
||||||
INFOPLIST_FILE = BankingiOSApp/Info.plist;
|
INFOPLIST_FILE = BankingiOSApp/Info.plist;
|
||||||
|
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
|
||||||
LD_RUNPATH_SEARCH_PATHS = (
|
LD_RUNPATH_SEARCH_PATHS = (
|
||||||
"$(inherited)",
|
"$(inherited)",
|
||||||
"@executable_path/Frameworks",
|
"@executable_path/Frameworks",
|
||||||
|
@ -886,7 +928,7 @@
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = net.dankito.banking.ios.BankingiOSApp.freeprovisioning;
|
PRODUCT_BUNDLE_IDENTIFIER = net.dankito.banking.ios.BankingiOSApp.freeprovisioning;
|
||||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
SWIFT_VERSION = 5.0;
|
SWIFT_VERSION = 5.0;
|
||||||
TARGETED_DEVICE_FAMILY = 1;
|
TARGETED_DEVICE_FAMILY = "1,2";
|
||||||
};
|
};
|
||||||
name = Release;
|
name = Release;
|
||||||
};
|
};
|
||||||
|
|
|
@ -89,6 +89,7 @@
|
||||||
"Enter TAN Dialog Title" = "Enter TAN";
|
"Enter TAN Dialog Title" = "Enter TAN";
|
||||||
"TAN procedure" = "TAN procedure";
|
"TAN procedure" = "TAN procedure";
|
||||||
"TAN medium" = "TAN medium";
|
"TAN medium" = "TAN medium";
|
||||||
|
"Tan Generator Frequency" = "Frequency";
|
||||||
"Size" = "Size";
|
"Size" = "Size";
|
||||||
"TAN hint from your bank:" = "Hint from your bank:";
|
"TAN hint from your bank:" = "Hint from your bank:";
|
||||||
"Enter TAN:" = "TAN";
|
"Enter TAN:" = "TAN";
|
||||||
|
|
|
@ -89,6 +89,7 @@
|
||||||
"Enter TAN Dialog Title" = "TAN-Abfrage";
|
"Enter TAN Dialog Title" = "TAN-Abfrage";
|
||||||
"TAN procedure" = "TAN Verfahren";
|
"TAN procedure" = "TAN Verfahren";
|
||||||
"TAN medium" = "TAN Medium";
|
"TAN medium" = "TAN Medium";
|
||||||
|
"Tan Generator Frequency" = "Geschw.";
|
||||||
"Size" = "Größe";
|
"Size" = "Größe";
|
||||||
"TAN hint from your bank:" = "Hinweis Ihrer Bank:";
|
"TAN hint from your bank:" = "Hinweis Ihrer Bank:";
|
||||||
"Enter TAN:" = "TAN";
|
"Enter TAN:" = "TAN";
|
||||||
|
|
|
@ -0,0 +1,89 @@
|
||||||
|
import SwiftUI
|
||||||
|
import BankingUiSwift
|
||||||
|
|
||||||
|
|
||||||
|
class FlickerCodeAnimator {
|
||||||
|
|
||||||
|
static let MinFrequency = 2
|
||||||
|
static let MaxFrequency = 40
|
||||||
|
static let DefaultFrequency = 30
|
||||||
|
|
||||||
|
private var currentFrequency: Int = DefaultFrequency
|
||||||
|
|
||||||
|
private var isPaused = false
|
||||||
|
|
||||||
|
private var currentStepIndex = 0
|
||||||
|
|
||||||
|
private var steps: [Step] = []
|
||||||
|
|
||||||
|
private var showStep: ((Step) -> Void)? = nil
|
||||||
|
|
||||||
|
private var timer: Timer? = nil
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
func animate(_ flickerCode: String, _ showStep: @escaping (Step) -> Void) {
|
||||||
|
self.stop() // stop may still running previous animation
|
||||||
|
|
||||||
|
self.steps = FlickerCodeStepsCalculator().calculateSteps(flickerCode: flickerCode)
|
||||||
|
|
||||||
|
self.showStep = showStep
|
||||||
|
|
||||||
|
self.start()
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private func start() {
|
||||||
|
currentStepIndex = 0
|
||||||
|
|
||||||
|
let interval = 1.0 / Double(currentFrequency)
|
||||||
|
|
||||||
|
timer = Timer.scheduledTimer(withTimeInterval: interval, repeats: true) { timer in
|
||||||
|
self.calculateAndShowNextStep()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private func calculateAndShowNextStep() {
|
||||||
|
if isPaused == false {
|
||||||
|
let nextStep = steps[currentStepIndex]
|
||||||
|
|
||||||
|
self.showStep?(nextStep)
|
||||||
|
|
||||||
|
currentStepIndex = currentStepIndex + 1
|
||||||
|
|
||||||
|
if (currentStepIndex >= steps.count) {
|
||||||
|
currentStepIndex = 0 // all steps shown, start again from beginning
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func stop() {
|
||||||
|
timer?.invalidate()
|
||||||
|
|
||||||
|
timer = nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func pause() {
|
||||||
|
self.isPaused = true
|
||||||
|
}
|
||||||
|
|
||||||
|
func resume() {
|
||||||
|
self.isPaused = false
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
func setFrequency(frequency: Int) {
|
||||||
|
if frequency >= Self.MinFrequency && frequency <= Self.MaxFrequency {
|
||||||
|
let isRunning = timer != nil
|
||||||
|
|
||||||
|
stop()
|
||||||
|
|
||||||
|
currentFrequency = frequency
|
||||||
|
|
||||||
|
if isRunning {
|
||||||
|
start()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -12,3 +12,27 @@ extension UIResponder {
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extension UserDefaults {
|
||||||
|
|
||||||
|
func string(forKey key: String, defaultValue: String) -> String {
|
||||||
|
return UserDefaults.standard.object(forKey: key) as? String ?? defaultValue
|
||||||
|
}
|
||||||
|
|
||||||
|
func integer(forKey key: String, defaultValue: Int) -> Int {
|
||||||
|
return UserDefaults.standard.object(forKey: key) as? Int ?? defaultValue
|
||||||
|
}
|
||||||
|
|
||||||
|
func float(forKey key: String, defaultValue: Float) -> Float {
|
||||||
|
return UserDefaults.standard.object(forKey: key) as? Float ?? defaultValue
|
||||||
|
}
|
||||||
|
|
||||||
|
func double(forKey key: String, defaultValue: Double) -> Double {
|
||||||
|
return UserDefaults.standard.object(forKey: key) as? Double ?? defaultValue
|
||||||
|
}
|
||||||
|
|
||||||
|
func bool(forKey key: String, defaultValue: Bool) -> Bool {
|
||||||
|
return UserDefaults.standard.object(forKey: key) as? Bool ?? defaultValue
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
|
@ -85,6 +85,11 @@ extension View {
|
||||||
.foregroundColor(amountColor)
|
.foregroundColor(amountColor)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
func turnAnimationOff() -> some View {
|
||||||
|
return self.animation(nil)
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -31,9 +31,9 @@ struct EnterTanDialog: View {
|
||||||
|
|
||||||
private var showSelectTanMediumView = false
|
private var showSelectTanMediumView = false
|
||||||
|
|
||||||
private var showFlickerCodeTanView = false
|
private let flickerCodeTanChallenge: FlickerCodeTanChallenge?
|
||||||
|
|
||||||
private var showImageTanView = false
|
private let imageTanChallenge: ImageTanChallenge?
|
||||||
|
|
||||||
@State private var enteredTan = ""
|
@State private var enteredTan = ""
|
||||||
|
|
||||||
|
@ -54,8 +54,8 @@ struct EnterTanDialog: View {
|
||||||
|
|
||||||
self.showSelectTanMediumView = self.customersTanMedia.count > 1 // TODO: use isOpticalTanProcedure && tanMedia.count > 1
|
self.showSelectTanMediumView = self.customersTanMedia.count > 1 // TODO: use isOpticalTanProcedure && tanMedia.count > 1
|
||||||
|
|
||||||
self.showFlickerCodeTanView = tanChallenge is FlickerCodeTanChallenge
|
self.flickerCodeTanChallenge = tanChallenge as? FlickerCodeTanChallenge
|
||||||
self.showImageTanView = tanChallenge is ImageTanChallenge
|
self.imageTanChallenge = tanChallenge as? ImageTanChallenge
|
||||||
|
|
||||||
if let decodingError = (tanChallenge as? FlickerCodeTanChallenge)?.flickerCode.decodingError {
|
if let decodingError = (tanChallenge as? FlickerCodeTanChallenge)?.flickerCode.decodingError {
|
||||||
showDecodingTanChallengeFailedErrorDelayed(decodingError)
|
showDecodingTanChallengeFailedErrorDelayed(decodingError)
|
||||||
|
@ -82,12 +82,12 @@ struct EnterTanDialog: View {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if showFlickerCodeTanView {
|
flickerCodeTanChallenge.map { flickerCodeTanChallenge in
|
||||||
Text("Entschuldigen Sie, aber die Darstellung von Flicker Codes wird gegenwärtig noch nicht unterstützt (fauler Programmierer). Bitte wählen Sie ein anderes TAN Verfahren, im Notfall chipTAN manuell.")
|
FlickerCodeTanView(flickerCodeTanChallenge)
|
||||||
}
|
}
|
||||||
|
|
||||||
if showImageTanView {
|
imageTanChallenge.map { imageTanChallenge in
|
||||||
ImageTanView(self.tanChallenge as! ImageTanChallenge)
|
ImageTanView(imageTanChallenge)
|
||||||
}
|
}
|
||||||
|
|
||||||
VStack {
|
VStack {
|
||||||
|
|
|
@ -0,0 +1,69 @@
|
||||||
|
import SwiftUI
|
||||||
|
|
||||||
|
|
||||||
|
struct FlickerCodeStripe: View {
|
||||||
|
|
||||||
|
private static let Height = CGFloat(100)
|
||||||
|
|
||||||
|
|
||||||
|
@Binding private var showBit: Bool
|
||||||
|
|
||||||
|
@Binding private var width: CGFloat
|
||||||
|
|
||||||
|
|
||||||
|
init(_ showBit: Binding<Bool>, _ width: Binding<CGFloat>) {
|
||||||
|
_showBit = showBit
|
||||||
|
_width = width
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
var body: some View {
|
||||||
|
Rectangle()
|
||||||
|
.fill(showBit ? Color.white : Color.black)
|
||||||
|
.frame(width: width, height: Self.Height)
|
||||||
|
.turnAnimationOff() // it's very important to turn animation off otherwise stripes get displayed in gray instead of white which TAN generator doesn't recognize
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
struct FlickerCodeBit_Previews: PreviewProvider {
|
||||||
|
|
||||||
|
static var previews: some View {
|
||||||
|
let bitWidth: CGFloat = 40
|
||||||
|
let spaceWidth: CGFloat = 15
|
||||||
|
|
||||||
|
return HStack {
|
||||||
|
Spacer()
|
||||||
|
|
||||||
|
HStack {
|
||||||
|
FlickerCodeStripe(.constant(true), .constant(bitWidth))
|
||||||
|
|
||||||
|
Spacer()
|
||||||
|
.frame(width: spaceWidth)
|
||||||
|
|
||||||
|
FlickerCodeStripe(.constant(true), .constant(bitWidth))
|
||||||
|
|
||||||
|
Spacer()
|
||||||
|
.frame(width: spaceWidth)
|
||||||
|
|
||||||
|
FlickerCodeStripe(.constant(true), .constant(bitWidth))
|
||||||
|
|
||||||
|
Spacer()
|
||||||
|
.frame(width: spaceWidth)
|
||||||
|
|
||||||
|
FlickerCodeStripe(.constant(false), .constant(bitWidth))
|
||||||
|
|
||||||
|
Spacer()
|
||||||
|
.frame(width: spaceWidth)
|
||||||
|
|
||||||
|
FlickerCodeStripe(.constant(true), .constant(bitWidth))
|
||||||
|
}
|
||||||
|
|
||||||
|
Spacer()
|
||||||
|
}
|
||||||
|
.frame(width: UIScreen.main.bounds.width)
|
||||||
|
.background(Color.black)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,188 @@
|
||||||
|
import SwiftUI
|
||||||
|
import BankingUiSwift
|
||||||
|
|
||||||
|
|
||||||
|
struct FlickerCodeTanView: View {
|
||||||
|
|
||||||
|
private static let FlickerCodeScaleFactorUserDefaultsKey = "FlickerCodeScaleFactor"
|
||||||
|
private static let FlickerCodeFrequencyDefaultsKey = "FlickerCodeFrequency"
|
||||||
|
|
||||||
|
private static let SpaceBetweenStripesStepSize: CGFloat = 0.5
|
||||||
|
private static let StripesWidthStepSize: CGFloat = 2.35 * Self.SpaceBetweenStripesStepSize
|
||||||
|
|
||||||
|
|
||||||
|
private let MinScaleFactor: CGFloat = 10
|
||||||
|
private let MaxScaleFactor: CGFloat
|
||||||
|
|
||||||
|
|
||||||
|
private var tanChallenge: BankingUiSwift.FlickerCodeTanChallenge
|
||||||
|
|
||||||
|
@State private var showBit1: Bool = true
|
||||||
|
@State private var showBit2: Bool = true
|
||||||
|
@State private var showBit3: Bool = true
|
||||||
|
@State private var showBit4: Bool = true
|
||||||
|
@State private var showBit5: Bool = true
|
||||||
|
|
||||||
|
private let animator: FlickerCodeAnimator = FlickerCodeAnimator()
|
||||||
|
|
||||||
|
private let timer = Timer.publish(every: 0.1, on: .main, in: .common).autoconnect()
|
||||||
|
|
||||||
|
|
||||||
|
@State private var frequency = CGFloat(UserDefaults.standard.float(forKey: Self.FlickerCodeFrequencyDefaultsKey, defaultValue: Float(FlickerCodeAnimator.DefaultFrequency)))
|
||||||
|
|
||||||
|
private var frequencyBinding: Binding<CGFloat> {
|
||||||
|
Binding<CGFloat>(
|
||||||
|
get: { self.frequency },
|
||||||
|
set: {
|
||||||
|
if (self.frequency != $0) {
|
||||||
|
let newFrequency = $0
|
||||||
|
|
||||||
|
self.animator.setFrequency(frequency: Int(newFrequency))
|
||||||
|
|
||||||
|
UserDefaults.standard.set(newFrequency, forKey: Self.FlickerCodeFrequencyDefaultsKey)
|
||||||
|
|
||||||
|
DispatchQueue.main.async {
|
||||||
|
self.frequency = newFrequency
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@State private var stripeWidth: CGFloat = 24
|
||||||
|
@State private var spaceBetweenStripes: CGFloat = 10
|
||||||
|
@State private var spaceBetweenTanGeneratorPositionMarker: CGFloat = 4 * 40 + 4 * 15 - TanGeneratorPositionMarker.Width
|
||||||
|
|
||||||
|
@State private var scaleFactor = CGFloat(UserDefaults.standard.float(forKey: Self.FlickerCodeScaleFactorUserDefaultsKey, defaultValue: 20.0))
|
||||||
|
|
||||||
|
private var scaleFactorBinding: Binding<CGFloat> {
|
||||||
|
Binding<CGFloat>(
|
||||||
|
get: { self.scaleFactor },
|
||||||
|
set: {
|
||||||
|
if (self.scaleFactor != $0) {
|
||||||
|
let newFlickerScaleFactor = $0
|
||||||
|
|
||||||
|
UserDefaults.standard.set(newFlickerScaleFactor, forKey: Self.FlickerCodeScaleFactorUserDefaultsKey)
|
||||||
|
|
||||||
|
DispatchQueue.main.async {
|
||||||
|
self.scaleFactor = newFlickerScaleFactor
|
||||||
|
|
||||||
|
self.calculateStripeWidth()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
init(_ tanChallenge: BankingUiSwift.FlickerCodeTanChallenge) {
|
||||||
|
self.tanChallenge = tanChallenge
|
||||||
|
|
||||||
|
let oneStepDiff = 5 * Self.StripesWidthStepSize + 4 * Self.SpaceBetweenStripesStepSize
|
||||||
|
MaxScaleFactor = CGFloat(Int(UIScreen.main.bounds.width / oneStepDiff))
|
||||||
|
|
||||||
|
animator.setFrequency(frequency: Int(frequency))
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
var body: some View {
|
||||||
|
Section {
|
||||||
|
HStack {
|
||||||
|
Text("Tan Generator Frequency")
|
||||||
|
|
||||||
|
Spacer()
|
||||||
|
|
||||||
|
Image(systemName: "tortoise")
|
||||||
|
|
||||||
|
Slider(value: frequencyBinding, in: CGFloat(FlickerCodeAnimator.MinFrequency)...CGFloat(FlickerCodeAnimator.MaxFrequency), step: 1)
|
||||||
|
|
||||||
|
Image(systemName: "hare")
|
||||||
|
}
|
||||||
|
|
||||||
|
ScaleImageView(scaleFactorBinding, imageMinWidth: MinScaleFactor, imageMaxWidth: MaxScaleFactor, step: 1)
|
||||||
|
|
||||||
|
VStack {
|
||||||
|
HStack {
|
||||||
|
Spacer()
|
||||||
|
|
||||||
|
TanGeneratorPositionMarker()
|
||||||
|
|
||||||
|
Spacer()
|
||||||
|
.frame(width: spaceBetweenTanGeneratorPositionMarker)
|
||||||
|
|
||||||
|
TanGeneratorPositionMarker()
|
||||||
|
|
||||||
|
Spacer()
|
||||||
|
}
|
||||||
|
.padding(.bottom, -4)
|
||||||
|
|
||||||
|
HStack {
|
||||||
|
Spacer()
|
||||||
|
|
||||||
|
HStack {
|
||||||
|
FlickerCodeStripe($showBit1, $stripeWidth)
|
||||||
|
|
||||||
|
Spacer()
|
||||||
|
.frame(width: spaceBetweenStripes)
|
||||||
|
|
||||||
|
FlickerCodeStripe($showBit2, $stripeWidth)
|
||||||
|
|
||||||
|
Spacer()
|
||||||
|
.frame(width: spaceBetweenStripes)
|
||||||
|
|
||||||
|
FlickerCodeStripe($showBit3, $stripeWidth)
|
||||||
|
|
||||||
|
Spacer()
|
||||||
|
.frame(width: spaceBetweenStripes)
|
||||||
|
|
||||||
|
FlickerCodeStripe($showBit4, $stripeWidth)
|
||||||
|
|
||||||
|
Spacer()
|
||||||
|
.frame(width: spaceBetweenStripes)
|
||||||
|
|
||||||
|
FlickerCodeStripe($showBit5, $stripeWidth)
|
||||||
|
}
|
||||||
|
|
||||||
|
Spacer()
|
||||||
|
}
|
||||||
|
.padding(.bottom, 12)
|
||||||
|
}
|
||||||
|
.background(Color.black)
|
||||||
|
.listRowInsets(EdgeInsets())
|
||||||
|
}
|
||||||
|
// what a hack to be able to call animator.animate() (otherwise compiler would throw 'use of immutable self in closure' error)
|
||||||
|
.onReceive(timer) { timer in
|
||||||
|
self.timer.upstream.connect().cancel()
|
||||||
|
|
||||||
|
self.calculateStripeWidth()
|
||||||
|
|
||||||
|
self.animator.animate(self.tanChallenge.flickerCode.parsedDataSet, self.showStep)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private func showStep(_ step: Step) {
|
||||||
|
self.showBit1 = step.bit1.isHigh
|
||||||
|
self.showBit2 = step.bit2.isHigh
|
||||||
|
self.showBit3 = step.bit3.isHigh
|
||||||
|
self.showBit4 = step.bit4.isHigh
|
||||||
|
self.showBit5 = step.bit5.isHigh
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private func calculateStripeWidth() {
|
||||||
|
stripeWidth = scaleFactor * Self.StripesWidthStepSize
|
||||||
|
spaceBetweenStripes = scaleFactor * Self.SpaceBetweenStripesStepSize
|
||||||
|
|
||||||
|
spaceBetweenTanGeneratorPositionMarker = 4 * stripeWidth + 4 * spaceBetweenStripes - TanGeneratorPositionMarker.Width
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
struct FlickerCodeTanView_Previews: PreviewProvider {
|
||||||
|
|
||||||
|
static var previews: some View {
|
||||||
|
FlickerCodeTanView(previewFlickerCodeTanChallenge)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -8,51 +8,19 @@ struct ImageTanView: View {
|
||||||
|
|
||||||
private var imageData: Data
|
private var imageData: Data
|
||||||
|
|
||||||
@State private var imageWidth: CGFloat
|
@State private var imageWidth: CGFloat = UIScreen.main.bounds.width / 2
|
||||||
|
|
||||||
private let imageMinWidth: CGFloat
|
|
||||||
|
|
||||||
private let imageMaxWidth: CGFloat
|
|
||||||
|
|
||||||
private let step: CGFloat
|
|
||||||
|
|
||||||
|
|
||||||
init(_ tanChallenge: ImageTanChallenge) {
|
init(_ tanChallenge: ImageTanChallenge) {
|
||||||
self.tanChallenge = tanChallenge
|
self.tanChallenge = tanChallenge
|
||||||
|
|
||||||
self.imageData = tanChallenge.image.imageBytesAsNSData()
|
self.imageData = tanChallenge.image.imageBytesAsNSData()
|
||||||
|
|
||||||
let screenWidth = UIScreen.main.bounds.width
|
|
||||||
let screenWidthQuarter = screenWidth / 4
|
|
||||||
|
|
||||||
self.imageMinWidth = screenWidthQuarter < 150 ? 150 : screenWidthQuarter // don't know whey but iOS seems that it doesn't scale image smaller than 150
|
|
||||||
self.imageMaxWidth = screenWidth
|
|
||||||
|
|
||||||
let range = imageMaxWidth - imageMinWidth
|
|
||||||
|
|
||||||
self._imageWidth = State(initialValue: imageMinWidth + range / 2)
|
|
||||||
|
|
||||||
self.step = range / 20
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
Section {
|
Section {
|
||||||
HStack {
|
ScaleImageView($imageWidth)
|
||||||
Text("Size")
|
|
||||||
|
|
||||||
Spacer()
|
|
||||||
|
|
||||||
Rectangle()
|
|
||||||
.fill(Color.gray)
|
|
||||||
.frame(width: 6, height: 9)
|
|
||||||
|
|
||||||
Slider(value: $imageWidth, in: imageMinWidth...imageMaxWidth, step: step)
|
|
||||||
|
|
||||||
Rectangle()
|
|
||||||
.fill(Color.gray)
|
|
||||||
.frame(width: 16, height: 19)
|
|
||||||
}
|
|
||||||
|
|
||||||
HStack {
|
HStack {
|
||||||
Spacer()
|
Spacer()
|
||||||
|
|
|
@ -0,0 +1,66 @@
|
||||||
|
import SwiftUI
|
||||||
|
|
||||||
|
|
||||||
|
struct ScaleImageView: View {
|
||||||
|
|
||||||
|
@Binding private var imageWidth: CGFloat
|
||||||
|
|
||||||
|
private let imageMinWidth: CGFloat
|
||||||
|
|
||||||
|
private let imageMaxWidth: CGFloat
|
||||||
|
|
||||||
|
private let step: CGFloat
|
||||||
|
|
||||||
|
|
||||||
|
init(_ imageWidth: Binding<CGFloat>, _ initialImageWidth: CGFloat? = nil) {
|
||||||
|
let screenWidth = UIScreen.main.bounds.width
|
||||||
|
let screenWidthQuarter = screenWidth / 4
|
||||||
|
|
||||||
|
let imageMinWidth = screenWidthQuarter < 150 ? 150 : screenWidthQuarter // don't know whey but iOS seems that it doesn't scale image smaller than 150
|
||||||
|
let imageMaxWidth = screenWidth
|
||||||
|
|
||||||
|
let range = imageMaxWidth - imageMinWidth
|
||||||
|
|
||||||
|
self.init(imageWidth, imageMinWidth: imageMinWidth, imageMaxWidth: imageMaxWidth, step: range / 20)
|
||||||
|
|
||||||
|
self.$imageWidth.wrappedValue = initialImageWidth ?? (imageMinWidth + range / 2)
|
||||||
|
}
|
||||||
|
|
||||||
|
init(_ imageWidth: Binding<CGFloat>, imageMinWidth: CGFloat, imageMaxWidth: CGFloat, step: CGFloat) {
|
||||||
|
_imageWidth = imageWidth
|
||||||
|
|
||||||
|
self.imageMinWidth = imageMinWidth
|
||||||
|
self.imageMaxWidth = imageMaxWidth
|
||||||
|
|
||||||
|
self.step = step
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
var body: some View {
|
||||||
|
HStack {
|
||||||
|
Text("Size")
|
||||||
|
|
||||||
|
Spacer()
|
||||||
|
|
||||||
|
Rectangle()
|
||||||
|
.fill(Color.gray) // TODO: use a system color
|
||||||
|
.frame(width: 6, height: 9)
|
||||||
|
|
||||||
|
Slider(value: $imageWidth, in: imageMinWidth...imageMaxWidth, step: step)
|
||||||
|
|
||||||
|
Rectangle()
|
||||||
|
.fill(Color.gray) // TODO: use a system color
|
||||||
|
.frame(width: 16, height: 19)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
struct ScaleImageView_Previews: PreviewProvider {
|
||||||
|
|
||||||
|
static var previews: some View {
|
||||||
|
ScaleImageView(.constant(250))
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,26 @@
|
||||||
|
import SwiftUI
|
||||||
|
|
||||||
|
|
||||||
|
struct TanGeneratorPositionMarker: View {
|
||||||
|
|
||||||
|
static let Width = CGFloat(24)
|
||||||
|
|
||||||
|
static let Height = CGFloat(24)
|
||||||
|
|
||||||
|
|
||||||
|
var body: some View {
|
||||||
|
TrianglePointingDown()
|
||||||
|
.fill(Color.gray)
|
||||||
|
.frame(width: Self.Width, height: Self.Height)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
struct TanGeneratorPositionMarker_Previews: PreviewProvider {
|
||||||
|
|
||||||
|
static var previews: some View {
|
||||||
|
TanGeneratorPositionMarker()
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,27 @@
|
||||||
|
import SwiftUI
|
||||||
|
|
||||||
|
|
||||||
|
struct TrianglePointingDown: Shape {
|
||||||
|
|
||||||
|
func path(in rect: CGRect) -> Path {
|
||||||
|
var path = Path()
|
||||||
|
|
||||||
|
path.move(to: CGPoint(x: rect.minX, y: rect.minY))
|
||||||
|
path.addLine(to: CGPoint(x: rect.maxX, y: rect.minY))
|
||||||
|
path.addLine(to: CGPoint(x: rect.midX, y: rect.maxY))
|
||||||
|
path.addLine(to: CGPoint(x: rect.minX, y: rect.minY))
|
||||||
|
|
||||||
|
return path
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
struct TrianglePointingDown_Previews: PreviewProvider {
|
||||||
|
|
||||||
|
static var previews: some View {
|
||||||
|
TrianglePointingDown()
|
||||||
|
.frame(width: 300, height: 300)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in New Issue