From fc9d471f3a099002153223c99ccdd5749e0dff83 Mon Sep 17 00:00:00 2001 From: nya3_neko2 Date: Fri, 15 Sep 2023 19:53:09 +0900 Subject: [PATCH 01/43] =?UTF-8?q?=E6=A9=9F=E8=83=BD=E5=AE=9F=E8=A3=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Keyboard/Display/InputManager.swift | 32 +++++++++----------- Keyboard/Display/KeyboardActionManager.swift | 5 ++- 2 files changed, 19 insertions(+), 18 deletions(-) diff --git a/Keyboard/Display/InputManager.swift b/Keyboard/Display/InputManager.swift index 296221b4..73f86aa4 100644 --- a/Keyboard/Display/InputManager.swift +++ b/Keyboard/Display/InputManager.swift @@ -225,12 +225,8 @@ import UIKit /// - parameters: /// - shouldModifyDisplayedText: DisplayedTextを操作して良いか否か。`textDidChange`などの場合は操作してはいけない。 func enter(shouldModifyDisplayedText: Bool = true) -> [ActionType] { - // selectedの場合、単に変換を止める - if isSelected { - self.stopComposition() - return [] - } var candidate: Candidate + // ライブ変換中に確定する場合、現在表示されているテキストそのものが候補となる。 if liveConversionEnabled, let _candidate = liveConversionManager.lastUsedCandidate { candidate = _candidate } else { @@ -286,6 +282,10 @@ import UIKit /// - simpleInsert: `ComposingText`を作るのではなく、直接文字を入力し、変換候補を表示しない。 /// - inputStyle: 入力スタイル func input(text: String, requireSetResult: Bool = true, simpleInsert: Bool = false, inputStyle: InputStyle) { + if self.isSelected { + // 選択部分を削除する + self.deleteSelection() + } // 直接入力の条件 if simpleInsert // flag || text == "\n" // 改行 @@ -293,19 +293,10 @@ import UIKit || self.keyboardLanguage == .none // 言語がnone { // 必要に応じて確定する - if !self.isSelected { - _ = self.enter() - } else { - self.stopComposition() - } + _ = self.enter() self.displayedTextManager.insertText(text) return } - // 直接入力にならない場合はまず選択部分を削除する - if self.isSelected { - // 選択部分を削除する - self.deleteSelection() - } self.composingText.insertAtCursorPosition(text, inputStyle: inputStyle) debug("Input Manager input:", composingText) if requireSetResult { @@ -680,15 +671,22 @@ import UIKit /// ユーザがキーボードを経由せずにカーソルを何かした場合の後処理を行う関数。 /// - note: この関数をユーティリティとして用いてはいけない。 - func userMovedCursor(count: Int) { + func userMovedCursor(count: Int) -> [ActionType]{ + var actions: [ActionType] = [] debug("userによるカーソル移動を検知、今の位置は\(composingText.convertTargetCursorPosition)、動かしたオフセットは\(count)") if composingText.isEmpty { // 入力がない場合はreturnしておかないと、入力していない時にカーソルを動かせなくなってしまう。 - return + actions.append(.setCursorBar(.on)) + return actions } let actualCount = composingText.moveCursorFromCursorPosition(count: count) self.previousSystemOperation = self.displayedTextManager.updateComposingText(composingText: self.composingText, userMovedCount: count, adjustedMovedCount: actualCount) ? .moveCursor : nil setResult() + // ライブ変換有効 + if liveConversionEnabled{ + actions.append(.setCursorBar(.on)) + } + return actions } /// ユーザがキーボードを経由せずカットした場合の処理 diff --git a/Keyboard/Display/KeyboardActionManager.swift b/Keyboard/Display/KeyboardActionManager.swift index a40341cb..86ca31be 100644 --- a/Keyboard/Display/KeyboardActionManager.swift +++ b/Keyboard/Display/KeyboardActionManager.swift @@ -539,7 +539,10 @@ import SwiftUtils if !wasSelected && !isSelected && b_left != a_left { debug("user operation id: 2", b_left, a_left) let offset = a_left.count - b_left.count - self.inputManager.userMovedCursor(count: offset) + let actions = self.inputManager.userMovedCursor(count: offset) + for action in actions{ + doAction(action, variableStates: variableStates) + } return } From 53deac88336cd7781d188528dea4c337f53b27c5 Mon Sep 17 00:00:00 2001 From: nya3_neko2 Date: Sun, 17 Sep 2023 15:44:14 +0900 Subject: [PATCH 02/43] =?UTF-8?q?=E3=82=B3=E3=83=A1=E3=83=B3=E3=83=88?= =?UTF-8?q?=E3=81=AB=E5=AF=BE=E3=81=97=E3=81=A6=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Keyboard/Display/InputManager.swift | 35 ++++++++++++-------- Keyboard/Display/KeyboardActionManager.swift | 5 +-- 2 files changed, 22 insertions(+), 18 deletions(-) diff --git a/Keyboard/Display/InputManager.swift b/Keyboard/Display/InputManager.swift index 73f86aa4..b1023150 100644 --- a/Keyboard/Display/InputManager.swift +++ b/Keyboard/Display/InputManager.swift @@ -225,8 +225,12 @@ import UIKit /// - parameters: /// - shouldModifyDisplayedText: DisplayedTextを操作して良いか否か。`textDidChange`などの場合は操作してはいけない。 func enter(shouldModifyDisplayedText: Bool = true) -> [ActionType] { + // selectedの場合、単に変換を止める + if isSelected { + self.stopComposition() + return [] + } var candidate: Candidate - // ライブ変換中に確定する場合、現在表示されているテキストそのものが候補となる。 if liveConversionEnabled, let _candidate = liveConversionManager.lastUsedCandidate { candidate = _candidate } else { @@ -282,10 +286,6 @@ import UIKit /// - simpleInsert: `ComposingText`を作るのではなく、直接文字を入力し、変換候補を表示しない。 /// - inputStyle: 入力スタイル func input(text: String, requireSetResult: Bool = true, simpleInsert: Bool = false, inputStyle: InputStyle) { - if self.isSelected { - // 選択部分を削除する - self.deleteSelection() - } // 直接入力の条件 if simpleInsert // flag || text == "\n" // 改行 @@ -293,10 +293,19 @@ import UIKit || self.keyboardLanguage == .none // 言語がnone { // 必要に応じて確定する - _ = self.enter() + if !self.isSelected { + _ = self.enter() + } else { + self.stopComposition() + } self.displayedTextManager.insertText(text) return } + // 直接入力にならない場合はまず選択部分を削除する + if self.isSelected { + // 選択部分を削除する + self.deleteSelection() + } self.composingText.insertAtCursorPosition(text, inputStyle: inputStyle) debug("Input Manager input:", composingText) if requireSetResult { @@ -671,22 +680,20 @@ import UIKit /// ユーザがキーボードを経由せずにカーソルを何かした場合の後処理を行う関数。 /// - note: この関数をユーティリティとして用いてはいけない。 - func userMovedCursor(count: Int) -> [ActionType]{ - var actions: [ActionType] = [] + func userMovedCursor(count: Int) -> [ActionType] { debug("userによるカーソル移動を検知、今の位置は\(composingText.convertTargetCursorPosition)、動かしたオフセットは\(count)") if composingText.isEmpty { // 入力がない場合はreturnしておかないと、入力していない時にカーソルを動かせなくなってしまう。 - actions.append(.setCursorBar(.on)) - return actions + return [.setCursorBar(.on)] } let actualCount = composingText.moveCursorFromCursorPosition(count: count) self.previousSystemOperation = self.displayedTextManager.updateComposingText(composingText: self.composingText, userMovedCount: count, adjustedMovedCount: actualCount) ? .moveCursor : nil setResult() // ライブ変換有効 - if liveConversionEnabled{ - actions.append(.setCursorBar(.on)) + if liveConversionEnabled { + return [.setCursorBar(.on)] } - return actions + return [] } /// ユーザがキーボードを経由せずカットした場合の処理 @@ -701,7 +708,7 @@ import UIKit // トークナイザ let tokenizer: CFStringTokenizer = CFStringTokenizerCreate( - kCFAllocatorDefault, + kCFAllocatorDefault, inputText as CFString, CFRangeMake(0, inputText.length), kCFStringTokenizerUnitWordBoundary, diff --git a/Keyboard/Display/KeyboardActionManager.swift b/Keyboard/Display/KeyboardActionManager.swift index 86ca31be..30d65eb7 100644 --- a/Keyboard/Display/KeyboardActionManager.swift +++ b/Keyboard/Display/KeyboardActionManager.swift @@ -539,10 +539,7 @@ import SwiftUtils if !wasSelected && !isSelected && b_left != a_left { debug("user operation id: 2", b_left, a_left) let offset = a_left.count - b_left.count - let actions = self.inputManager.userMovedCursor(count: offset) - for action in actions{ - doAction(action, variableStates: variableStates) - } + registerActions(self.inputManager.userMovedCursor(count: offset), variableStates: variableStates) return } From 55f4e91e0d50db89f8514a4387cd01187bf97274 Mon Sep 17 00:00:00 2001 From: nya3_neko2 Date: Sun, 17 Sep 2023 15:57:21 +0900 Subject: [PATCH 03/43] =?UTF-8?q?Swift=20lint=E3=81=A7=E3=81=AE=E5=A4=89?= =?UTF-8?q?=E6=9B=B4=E5=88=86=E3=82=92=E8=BF=BD=E5=8A=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Keyboard/Display/KeyboardActionManager.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Keyboard/Display/KeyboardActionManager.swift b/Keyboard/Display/KeyboardActionManager.swift index 30d65eb7..9d03b8e2 100644 --- a/Keyboard/Display/KeyboardActionManager.swift +++ b/Keyboard/Display/KeyboardActionManager.swift @@ -332,7 +332,7 @@ import SwiftUtils self.registerActions(action.start, variableStates: variableStates) } self.tasks.append((type: action, task: startTask)) - + let repeatTask = Task { try await Task.sleep(nanoseconds: 0_400_000_000) while !Task.isCancelled { From 9af653dc7ae3ffc3c1e25a5dbb72fad0c4286662 Mon Sep 17 00:00:00 2001 From: ensan-hcl Date: Thu, 12 Oct 2023 00:16:26 +0900 Subject: [PATCH 04/43] Update focus implementation to make the focus more clear --- MainApp/General/Focus.swift | 9 +++------ .../FlickCustomKeys/CustomKeySettingFlickKeyView.swift | 1 + .../QwertyCustomKeys/QwertyCustomKeysItemView.swift | 2 ++ 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/MainApp/General/Focus.swift b/MainApp/General/Focus.swift index adbb9a51..ef739781 100644 --- a/MainApp/General/Focus.swift +++ b/MainApp/General/Focus.swift @@ -18,17 +18,14 @@ private struct FocusViewModifier: ViewModifier { func body(content: Content) -> some View { let shadowColor = focused ? color : .clear - let shadowRadius: CGFloat = focused ? 0.5 : .zero + let shadowRadius: CGFloat = focused ? 3.0 : .zero return content - .shadow(color: shadowColor, radius: shadowRadius, x: 1) - .shadow(color: shadowColor, radius: shadowRadius, x: -1) - .shadow(color: shadowColor, radius: shadowRadius, y: 1) - .shadow(color: shadowColor, radius: shadowRadius, y: -1) + .shadow(color: shadowColor, radius: shadowRadius) } } extension View { - func focus(_ color: Color, focused: Bool) -> some View { + func focus(_ color: Color = .accentColor, focused: Bool) -> some View { self.modifier(FocusViewModifier(color: color, focused: focused)) } } diff --git a/MainApp/Setting/CustomKeys/FlickCustomKeys/CustomKeySettingFlickKeyView.swift b/MainApp/Setting/CustomKeys/FlickCustomKeys/CustomKeySettingFlickKeyView.swift index bbb13a8b..0ff3d358 100644 --- a/MainApp/Setting/CustomKeys/FlickCustomKeys/CustomKeySettingFlickKeyView.swift +++ b/MainApp/Setting/CustomKeys/FlickCustomKeys/CustomKeySettingFlickKeyView.swift @@ -39,6 +39,7 @@ struct CustomKeySettingFlickKeyView: View { RoundedRectangle(cornerRadius: 10) .stroke(strokeColor) .background(RoundedRectangle(cornerRadius: 10).fill(Color.background)) + .compositingGroup() .focus(.accentColor, focused: focused) .overlay(label()) .onTapGesture { diff --git a/MainApp/Setting/CustomKeys/QwertyCustomKeys/QwertyCustomKeysItemView.swift b/MainApp/Setting/CustomKeys/QwertyCustomKeys/QwertyCustomKeysItemView.swift index 3b65800c..6acb887c 100644 --- a/MainApp/Setting/CustomKeys/QwertyCustomKeys/QwertyCustomKeysItemView.swift +++ b/MainApp/Setting/CustomKeys/QwertyCustomKeys/QwertyCustomKeysItemView.swift @@ -165,6 +165,7 @@ struct QwertyCustomKeysSettingView: RoundedRectangle(cornerRadius: 10) .stroke(strokeColor) .background(RoundedRectangle(cornerRadius: 10).fill(Color.background)) + .compositingGroup() .focus(.accentColor, focused: isSelected && selection.longpressSelectIndex == -1) .focus(.systemGray, focused: isSelected && selection.longpressSelectIndex != -1) .overlay(Text(item.name)) @@ -179,6 +180,7 @@ struct QwertyCustomKeysSettingView: RoundedRectangle(cornerRadius: 10) .stroke(isSelected ? Color.accentColor : .primary) .background(RoundedRectangle(cornerRadius: 10).fill(Color.background)) + .compositingGroup() .focus(.accentColor, focused: isSelected) .overlay(Text(item.name)) } From f48ce34e1b9a01a79bc10610ca3aea301d414096 Mon Sep 17 00:00:00 2001 From: ensan-hcl Date: Thu, 12 Oct 2023 01:17:18 +0900 Subject: [PATCH 05/43] Add special animation to acknowledgement page --- .../Sources/KeyboardViews/AzooKeyIcon.swift | 4 + .../OpenSourceSoftwaresLicenseView.swift | 109 +++++++++++++++++- 2 files changed, 112 insertions(+), 1 deletion(-) diff --git a/AzooKeyCore/Sources/KeyboardViews/AzooKeyIcon.swift b/AzooKeyCore/Sources/KeyboardViews/AzooKeyIcon.swift index 8727933e..214f177c 100644 --- a/AzooKeyCore/Sources/KeyboardViews/AzooKeyIcon.swift +++ b/AzooKeyCore/Sources/KeyboardViews/AzooKeyIcon.swift @@ -18,6 +18,7 @@ public struct AzooKeyIcon: View { case king case santaClaus case strawHat + case fire } public enum Color { case auto @@ -88,6 +89,9 @@ public struct AzooKeyIcon: View { Text("\u{EA22}") .foregroundStyle(.red) } + case .fire: + Text("δ") + .foregroundStyle(foregroundColor) } } diff --git a/MainApp/Setting/OpenSourceSoftwaresLicenseView.swift b/MainApp/Setting/OpenSourceSoftwaresLicenseView.swift index 599beced..de18234d 100644 --- a/MainApp/Setting/OpenSourceSoftwaresLicenseView.swift +++ b/MainApp/Setting/OpenSourceSoftwaresLicenseView.swift @@ -193,7 +193,7 @@ struct OpenSourceSoftwaresLicenseView: View { } Section { HStack { - AzooKeyIcon(fontSize: 60) + FunnyAzooKeyIcon() Spacer() Text("azooKeyを使ってくれてありがとう!") } @@ -203,3 +203,110 @@ struct OpenSourceSoftwaresLicenseView: View { .navigationBarTitle(Text("オープンソースソフトウェア"), displayMode: .inline) } } + +private struct FunnyAzooKeyIcon: View { + init(stage: Stage = .normal) { + self._stage = .init(initialValue: stage) + } + + struct NormalAnimationValue { + // degrees + var angle: Double = -10 + } + struct KingAnimationValue { + // degrees + var yAngle: Double = -10 + var scale: Double = 1.0 + } + struct FireAnimationValue { + // degrees + var yAngle: Double = 0 + var scale: Double = 1.0 + } + enum Stage { + case normal + case king + case fire + } + @Namespace private var namespace + @State private var stage: Stage = .normal + + private var iconCore: some View { + AzooKeyIcon(fontSize: 60) + .matchedGeometryEffect(id: "icon", in: namespace) + } + + var body: some View { + if #available(iOS 17, *) { + switch stage { + case .normal: + iconCore + .keyframeAnimator(initialValue: NormalAnimationValue()) { content, value in + content + .rotationEffect(Angle(degrees: value.angle)) + } keyframes: { _ in + KeyframeTrack(\.angle) { + CubicKeyframe(10, duration: 0.5) + CubicKeyframe(-10, duration: 0.5) + } + } + .onTapGesture { + withAnimation { + self.stage = Bool.random() ? .king : .fire + } + } + case .king: + AzooKeyIcon(fontSize: 60, looks: .king) + .matchedGeometryEffect(id: "icon", in: namespace) + .keyframeAnimator(initialValue: KingAnimationValue()) { content, value in + content + .rotationEffect(Angle(degrees: value.yAngle)) + .scaleEffect(value.scale) + } keyframes: { _ in + KeyframeTrack(\.yAngle) { + CubicKeyframe(10, duration: 0.5) + CubicKeyframe(-10, duration: 0.5) + } + KeyframeTrack(\.scale) { + SpringKeyframe(1, duration: 0.2) + SpringKeyframe(1.4, duration: 0.6) + SpringKeyframe(1, duration: 0.2) + } + } + .onTapGesture { + withAnimation { + self.stage = .normal + } + } + case .fire: + AzooKeyIcon(fontSize: 60, looks: .fire) + .matchedGeometryEffect(id: "icon", in: namespace) + .keyframeAnimator(initialValue: FireAnimationValue()) { content, value in + content + .rotationEffect(Angle(degrees: value.yAngle)) + .scaleEffect(value.scale) + } keyframes: { _ in + KeyframeTrack(\.yAngle) { + SpringKeyframe(20, duration: 0.8) + CubicKeyframe(0, duration: 0.2) + } + } + .onTapGesture { + withAnimation { + self.stage = .normal + } + } + } + } else { + iconCore + } + } +} + +#Preview { + VStack { + FunnyAzooKeyIcon(stage: .normal) + FunnyAzooKeyIcon(stage: .king) + FunnyAzooKeyIcon(stage: .fire) + } +} From 8b5b4bb2da8e893ecd0c2e673c51a85fa5d5b34d Mon Sep 17 00:00:00 2001 From: ensan-hcl Date: Thu, 12 Oct 2023 02:05:28 +0900 Subject: [PATCH 06/43] Update tab abr editor usability --- MainApp/Customize/EditingTabBarView.swift | 127 +++++++++++++--------- Resources/Localizable.xcstrings | 40 +++++++ 2 files changed, 114 insertions(+), 53 deletions(-) diff --git a/MainApp/Customize/EditingTabBarView.swift b/MainApp/Customize/EditingTabBarView.swift index a41a8bb2..ba63e586 100644 --- a/MainApp/Customize/EditingTabBarView.swift +++ b/MainApp/Customize/EditingTabBarView.swift @@ -44,57 +44,89 @@ struct EditingTabBarView: View { self._manager = manager } + private static let anchorId = "BOTTOM_ANCHOR" var body: some View { - Form { - Text("タブバーを編集し、タブの並び替え、削除、追加を行ったり、文字の入力やカーソルの移動など様々な機能を追加することができます。") - Section { - Button(action: add) { - Label("アイテムを追加", systemImage: "plus") + ScrollViewReader { proxy in + Form { + Text("タブバーを編集し、タブの並び替え、削除、追加を行ったり、文字の入力やカーソルの移動など様々な機能を追加することができます。") + Section { + Button("アイテムを追加", systemImage: "plus") { + withAnimation(.interactiveSpring()) { + let item = EditingTabBarItem( + label: .text("アイテム"), + actions: [.moveTab(.system(.user_japanese))] + ) + self.items.append(item) + proxy.scrollTo(Self.anchorId, anchor: .bottom) + } + } } - } - Section(header: Text("アイテム")) { - DisclosuringList($items) { $item in - HStack { - Label("ラベル", systemImage: "rectangle.and.pencil.and.ellipsis") - Spacer() - TabNavigationViewItemLabelEditView("ラベルを設定", label: $item.label) + Section(header: Text("アイテム")) { + DisclosuringList($items) { $item in + HStack { + Label("ラベル", systemImage: "rectangle.and.pencil.and.ellipsis") + Spacer() + TabNavigationViewItemLabelEditView("ラベルを設定", label: $item.label) + } + NavigationLink(destination: CodableActionDataEditor($item.actions, availableCustards: manager.availableCustards)) { + Label("アクション", systemImage: "terminal") + Text(makeLabelText(item: item)) + .foregroundStyle(.gray) + } + } label: { item in + label(labelType: item.label) + .contextMenu { + Button(role: .destructive) { + items.removeAll(where: {$0.id == item.id}) + } label: { + Label("削除", systemImage: "trash") + } + } } - NavigationLink(destination: CodableActionDataEditor($item.actions, availableCustards: manager.availableCustards)) { - Label("アクション", systemImage: "terminal") - - Text(makeLabelText(item: item)) - .foregroundStyle(.gray) + .onDelete(perform: delete) + .onMove(perform: move) + } + Section(header: Text("便利なボタンを追加")) { + Button("片手モードをオン", systemImage: "aspectratio") { + withAnimation(.interactiveSpring()) { + self.items.append(EditingTabBarItem(label: .text("片手"), actions: [.enableResizingMode])) + } } - } label: { item in - label(labelType: item.label) - .contextMenu { - Button(role: .destructive) { - items.removeAll(where: {$0.id == item.id}) - } label: { - Label("削除", systemImage: "trash") - } + .id(Self.anchorId) // ココに付けると自動スクロールが機能する + Button("絵文字タブを表示", systemImage: "face.smiling") { + withAnimation(.interactiveSpring()) { + self.items.append(EditingTabBarItem(label: .text("絵文字"), actions: [.moveTab(.system(.emoji_tab))])) + } + } + Button("カーソルバーを表示", systemImage: "arrowtriangle.left.and.line.vertical.and.arrowtriangle.right") { + withAnimation(.interactiveSpring()) { + self.items.append(EditingTabBarItem(label: .text("カーソル移動"), actions: [.toggleCursorBar])) } + } + Button("キーボードを閉じる", systemImage: "keyboard.chevron.compact.down") { + withAnimation(.interactiveSpring()) { + self.items.append(EditingTabBarItem(label: .text("閉じる"), actions: [.dismissKeyboard])) + } + } } - .onDelete(perform: delete) - .onMove(perform: move) } - } - .onAppear { - if let tabBarData = try? manager.tabbar(identifier: 0), tabBarData.lastUpdateDate != self.lastUpdateDate { - self.items = tabBarData.items.indices.map {i in - EditingTabBarItem( - label: tabBarData.items[i].label, - actions: tabBarData.items[i].actions - ) + .onAppear { + if let tabBarData = try? manager.tabbar(identifier: 0), tabBarData.lastUpdateDate != self.lastUpdateDate { + self.items = tabBarData.items.indices.map {i in + EditingTabBarItem( + label: tabBarData.items[i].label, + actions: tabBarData.items[i].actions + ) + } } } + .onChange(of: items) {newValue in + self.save(newValue) + } + .navigationBarTitle(Text("タブバーの編集"), displayMode: .inline) + .navigationBarItems(trailing: editButton) + .environment(\.editMode, $editMode) } - .onChange(of: items) {newValue in - self.save(newValue) - } - .navigationBarTitle(Text("タブバーの編集"), displayMode: .inline) - .navigationBarItems(trailing: editButton) - .environment(\.editMode, $editMode) } @ViewBuilder private func label(labelType: TabBarItemLabelType) -> some View { @@ -149,7 +181,7 @@ struct EditingTabBarView: View { } label: { switch editMode { case .inactive: - Text("削除と順番") + Text("編集") case .active, .transient: Text("完了") @unknown default: @@ -158,17 +190,6 @@ struct EditingTabBarView: View { } } - private func add() { - withAnimation(Animation.interactiveSpring()) { - items.append( - EditingTabBarItem( - label: .text("アイテム"), - actions: [.moveTab(.system(.user_japanese))] - ) - ) - } - } - private func delete(at offsets: IndexSet) { items.remove(atOffsets: offsets) } diff --git a/Resources/Localizable.xcstrings b/Resources/Localizable.xcstrings index 744d6a0b..7bfb0cbd 100644 --- a/Resources/Localizable.xcstrings +++ b/Resources/Localizable.xcstrings @@ -1925,6 +1925,16 @@ } } }, + "カーソルバーを表示" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Show cursor bar" + } + } + } + }, "カーソルを移動する" : { "localizations" : { "en" : { @@ -5356,6 +5366,16 @@ } } }, + "便利なボタンを追加" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Add useful buttons" + } + } + } + }, "便利な使い方" : { "localizations" : { "en" : { @@ -8522,6 +8542,16 @@ } } }, + "絵文字タブを表示" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Show emoji tab" + } + } + } + }, "絵文字と顔文字" : { "localizations" : { "en" : { @@ -8602,6 +8632,16 @@ } } }, + "編集" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Edit" + } + } + } + }, "編集が終わったら完了ボタンを押してください。" : { "localizations" : { "en" : { From abf4716520bf9be5ad9e144495e68c7c5d6a4ba6 Mon Sep 17 00:00:00 2001 From: ensan-hcl Date: Thu, 12 Oct 2023 12:54:12 +0900 Subject: [PATCH 07/43] Stop using weird twerk to show the azooKey logo --- MainApp/General/HeaderLogoView.swift | 6 +- MainApp/Tips/TipsView.swift | 85 ++++++++++++++-------------- 2 files changed, 48 insertions(+), 43 deletions(-) diff --git a/MainApp/General/HeaderLogoView.swift b/MainApp/General/HeaderLogoView.swift index 0fa2d0c6..cb859a27 100644 --- a/MainApp/General/HeaderLogoView.swift +++ b/MainApp/General/HeaderLogoView.swift @@ -33,7 +33,9 @@ struct HeaderLogoView: View { } } .foregroundStyle(iconColor) - .padding(.top, 5) - .padding(.bottom, -5) } } + +#Preview { + HeaderLogoView() +} diff --git a/MainApp/Tips/TipsView.swift b/MainApp/Tips/TipsView.swift index 6b4402c3..10a912aa 100644 --- a/MainApp/Tips/TipsView.swift +++ b/MainApp/Tips/TipsView.swift @@ -14,56 +14,59 @@ struct TipsTabView: View { @AppStorage("read_article_iOS15_service_termination") private var readArticle_iOS15_service_termination = false var body: some View { - VStack { - HeaderLogoView() - NavigationView { - Form { - Section(header: Text("キーボードを使えるようにする")) { - if !appStates.isKeyboardActivated { - Text("キーボードを有効化する") - .onTapGesture { - appStates.requireFirstOpenView = true - } - } - NavigationLink("入力方法を選ぶ", destination: SelctInputStyleTipsView()) + NavigationView { + Form { + Section(header: Text("キーボードを使えるようにする")) { + if !appStates.isKeyboardActivated { + Text("キーボードを有効化する") + .onTapGesture { + appStates.requireFirstOpenView = true + } } - if #unavailable(iOS 16) { - Section(header: Text("お知らせ")) { - HStack { - if !readArticle_iOS15_service_termination { - Image(systemName: "exclamationmark.circle.fill") - .foregroundStyle(.red) - } - NavigationLink("iOS15のサポートを終了します", destination: iOS15TerminationNewsView($readArticle_iOS15_service_termination)) + NavigationLink("入力方法を選ぶ", destination: SelctInputStyleTipsView()) + } + if #unavailable(iOS 16) { + Section(header: Text("お知らせ")) { + HStack { + if !readArticle_iOS15_service_termination { + Image(systemName: "exclamationmark.circle.fill") + .foregroundStyle(.red) } + NavigationLink("iOS15のサポートを終了します", destination: iOS15TerminationNewsView($readArticle_iOS15_service_termination)) } } + } - Section(header: Text("便利な使い方")) { - NavigationLink("片手モードを使う", destination: OneHandedModeTipsView()) - NavigationLink("カーソルを自由に移動する", destination: CursorMoveTipsView()) - NavigationLink("文頭まで一気に消す", destination: SmoothDeleteTipsView()) - NavigationLink("漢字を拡大表示する", destination: KanjiLargeTextTipsView()) - NavigationLink("大文字に固定する", destination: CapsLockTipsView()) - NavigationLink("タイムスタンプを使う", destination: TemplateSettingTipsView()) - NavigationLink("キーをカスタマイズする", destination: CustomKeyTipsView()) - NavigationLink("フルアクセスが必要な機能を使う", destination: FullAccessTipsView()) - if SemiStaticStates.shared.hasFullAccess { - NavigationLink("「ほかのAppからペースト」について", destination: PasteFromOtherAppsPermissionTipsView()) - } + Section(header: Text("便利な使い方")) { + NavigationLink("片手モードを使う", destination: OneHandedModeTipsView()) + NavigationLink("カーソルを自由に移動する", destination: CursorMoveTipsView()) + NavigationLink("文頭まで一気に消す", destination: SmoothDeleteTipsView()) + NavigationLink("漢字を拡大表示する", destination: KanjiLargeTextTipsView()) + NavigationLink("大文字に固定する", destination: CapsLockTipsView()) + NavigationLink("タイムスタンプを使う", destination: TemplateSettingTipsView()) + NavigationLink("キーをカスタマイズする", destination: CustomKeyTipsView()) + NavigationLink("フルアクセスが必要な機能を使う", destination: FullAccessTipsView()) + if SemiStaticStates.shared.hasFullAccess { + NavigationLink("「ほかのAppからペースト」について", destination: PasteFromOtherAppsPermissionTipsView()) } + } - Section(header: Text("困ったときは")) { - NavigationLink("インストール直後、特定のアプリでキーボードが開かない", destination: KeyboardBehaviorIssueAfterInstallTipsView()) - NavigationLink("特定のアプリケーションで入力がおかしくなる", destination: UseMarkedTextTipsView()) - NavigationLink("端末の文字サイズ設定が反映されない", destination: DynamicTypeSettingFailureTipsView()) - NavigationLink("絵文字や顔文字の変換候補を表示したい", destination: EmojiKaomojiTipsView()) - NavigationLink("バグの報告や機能のリクエストをしたい", destination: ContactView()) - } + Section(header: Text("困ったときは")) { + NavigationLink("インストール直後、特定のアプリでキーボードが開かない", destination: KeyboardBehaviorIssueAfterInstallTipsView()) + NavigationLink("特定のアプリケーションで入力がおかしくなる", destination: UseMarkedTextTipsView()) + NavigationLink("端末の文字サイズ設定が反映されない", destination: DynamicTypeSettingFailureTipsView()) + NavigationLink("絵文字や顔文字の変換候補を表示したい", destination: EmojiKaomojiTipsView()) + NavigationLink("バグの報告や機能のリクエストをしたい", destination: ContactView()) + } + } + .navigationBarTitleDisplayMode(.inline) + .toolbar { + ToolbarItem(placement: .principal) { + HeaderLogoView() + .padding(.vertical, 4) } - .navigationBarTitle(Text("使い方"), displayMode: .large) } - .navigationViewStyle(.stack) } + .navigationViewStyle(.stack) } } From 0f46370499f669395585e391c58c8bc5a1eee052 Mon Sep 17 00:00:00 2001 From: ensan-hcl Date: Thu, 12 Oct 2023 15:37:28 +0900 Subject: [PATCH 08/43] Make tutorial more smart design in iPad --- MainApp/Customize/CustomizeTabWalkthrough.swift | 1 + MainApp/EnableAzooKeyView/EnableAzooKeyView.swift | 12 +++++++++--- .../EnableAzooKeyViewComponent.swift | 1 + MainApp/General/LargeButtonStyle.swift | 6 ++---- 4 files changed, 13 insertions(+), 7 deletions(-) diff --git a/MainApp/Customize/CustomizeTabWalkthrough.swift b/MainApp/Customize/CustomizeTabWalkthrough.swift index 2b6925f9..0c4a3896 100644 --- a/MainApp/Customize/CustomizeTabWalkthrough.swift +++ b/MainApp/Customize/CustomizeTabWalkthrough.swift @@ -84,6 +84,7 @@ struct CustomizeTabWalkthroughView: View { } .buttonStyle(LargeButtonStyle(backgroundColor: .blue)) .foregroundStyle(.white) + .padding(.horizontal, 20) .padding(.top, 30) } .background(Color.background) diff --git a/MainApp/EnableAzooKeyView/EnableAzooKeyView.swift b/MainApp/EnableAzooKeyView/EnableAzooKeyView.swift index 4269783c..be060316 100644 --- a/MainApp/EnableAzooKeyView/EnableAzooKeyView.swift +++ b/MainApp/EnableAzooKeyView/EnableAzooKeyView.swift @@ -62,9 +62,13 @@ struct EnableAzooKeyView: View { EnableAzooKeyViewHeader("追加する") EnableAzooKeyViewText("下にスクロールして「追加する」を押して", with: "plus.circle") EnableAzooKeyViewText("「キーボード」を押して", with: "keyboard") - EnableAzooKeyViewImage(.initSettingKeyboardImageHand) + CenterAlignedView { + EnableAzooKeyViewImage(.initSettingKeyboardImageHand) + } EnableAzooKeyViewText("azooKeyをオンにして", with: "square.and.line.vertical.and.square.fill") - EnableAzooKeyViewImage(.initSettingAzooKeySwitchImageHand) + CenterAlignedView { + EnableAzooKeyViewImage(.initSettingAzooKeySwitchImageHand) + } EnableAzooKeyViewText("このアプリを再び開いてください", with: "arrow.turn.down.left") CenterAlignedView { EnableAzooKeyViewButton("追加する", systemName: "plus.circle") { @@ -134,7 +138,9 @@ struct EnableAzooKeyView: View { appStates.requireFirstOpenView = false } if !showDoneMessage { - EnableAzooKeyViewImage(.initSettingGlobeTap) + CenterAlignedView { + EnableAzooKeyViewImage(.initSettingGlobeTap) + } } EnableAzooKeyViewText("azooKeyをお楽しみください!", with: "star.fill") if !showDoneMessage { diff --git a/MainApp/EnableAzooKeyView/EnableAzooKeyViewComponent.swift b/MainApp/EnableAzooKeyView/EnableAzooKeyViewComponent.swift index 0574c628..dc91d28e 100644 --- a/MainApp/EnableAzooKeyView/EnableAzooKeyViewComponent.swift +++ b/MainApp/EnableAzooKeyView/EnableAzooKeyViewComponent.swift @@ -100,5 +100,6 @@ struct EnableAzooKeyViewImage: View { .resizable() .scaledToFit() .cornerRadius(2) + .frame(maxWidth: MainAppDesign.imageMaximumWidth) } } diff --git a/MainApp/General/LargeButtonStyle.swift b/MainApp/General/LargeButtonStyle.swift index db683860..f17380b3 100644 --- a/MainApp/General/LargeButtonStyle.swift +++ b/MainApp/General/LargeButtonStyle.swift @@ -10,19 +10,17 @@ import SwiftUI struct LargeButtonStyle: ButtonStyle { private let backgroundColor: Color - private let screenWidth: CGFloat @MainActor init(backgroundColor: Color) { self.backgroundColor = backgroundColor - self.screenWidth = UIScreen.main.bounds.width } @ViewBuilder func makeBody(configuration: Configuration) -> some View { configuration .label .font(.body.bold()) .padding() - .frame(width: screenWidth * 0.9) + .frame(maxWidth: .infinity) .background( - RoundedRectangle(cornerRadius: screenWidth / 4.8 * 0.17) + RoundedRectangle(cornerRadius: 12) .fill(backgroundColor) ) .opacity(configuration.isPressed ? 0.8 : 1) From 52af458a422495afff1bdb3bdb7c9ebdc4e17cc6 Mon Sep 17 00:00:00 2001 From: ensan-hcl Date: Fri, 13 Oct 2023 11:09:31 +0900 Subject: [PATCH 09/43] Fix broken layout --- .../Customize/CustomizeTabWalkthrough.swift | 33 ++++++++++--------- 1 file changed, 17 insertions(+), 16 deletions(-) diff --git a/MainApp/Customize/CustomizeTabWalkthrough.swift b/MainApp/Customize/CustomizeTabWalkthrough.swift index 0c4a3896..22b7c563 100644 --- a/MainApp/Customize/CustomizeTabWalkthrough.swift +++ b/MainApp/Customize/CustomizeTabWalkthrough.swift @@ -60,25 +60,26 @@ struct CustomizeTabWalkthroughView: View { Text("azooKeyを拡張する").font(.largeTitle.bold()) .padding() let imagesFont: Font = Font.system(size: length / 2.4, weight: .light, design: .default) - ForEach(items) {item in - HStack { - Image(systemName: item.image) - .font(imagesFont) - .frame(width: geometry.size.width / 7.0, height: geometry.size.width / 7.0) - .foregroundStyle(.blue) - VStack(alignment: .leading) { - Text(item.headline) - .font(.subheadline.bold()) - Text(item.body) - .foregroundStyle(.gray) - .font(.subheadline) + VStack(alignment: .leading, spacing: 20) { + ForEach(items) {item in + HStack { + Image(systemName: item.image) + .font(imagesFont) + .frame(width: geometry.size.width / 7.0, height: geometry.size.width / 7.0) + .foregroundStyle(.blue) + VStack(alignment: .leading) { + Text(item.headline) + .font(.subheadline.bold()) + Text(item.body) + .foregroundStyle(.gray) + .font(.subheadline) + } } + .padding(.horizontal, 20) + .lineLimit(nil) + .fixedSize(horizontal: false, vertical: true) } - .padding(.horizontal, 20) - .lineLimit(nil) - .fixedSize(horizontal: false, vertical: true) } - Button("始める") { isShowing = false } From 953a90c237165eb818a2f4c0905913b5fcc6efdb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Naoki=20Takahashi=20/=20=E9=9B=BB=E9=9B=BB=E7=8C=AB?= =?UTF-8?q?=E7=8C=AB?= <43579605+nyanko3141592@users.noreply.github.com> Date: Sun, 15 Oct 2023 20:04:59 +0900 Subject: [PATCH 10/43] =?UTF-8?q?=E9=81=B8=E6=8A=9E=E3=81=97=E3=81=A6?= =?UTF-8?q?=E3=81=84=E3=82=8B=E3=83=86=E3=82=AD=E3=82=B9=E3=83=88=E3=81=8C?= =?UTF-8?q?=E3=81=82=E3=82=8B=E5=A0=B4=E5=90=88=E3=81=AB=E3=83=AA=E3=82=B6?= =?UTF-8?q?=E3=83=AB=E3=83=88=E3=83=90=E3=83=BC=E3=81=AE=E8=A1=A8=E7=A4=BA?= =?UTF-8?q?=E3=82=92=E3=81=99=E3=82=8B=E3=82=88=E3=81=86=E3=81=AB=E4=BF=AE?= =?UTF-8?q?=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Keyboard/Display/InputManager.swift | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/Keyboard/Display/InputManager.swift b/Keyboard/Display/InputManager.swift index b1023150..6e20b81a 100644 --- a/Keyboard/Display/InputManager.swift +++ b/Keyboard/Display/InputManager.swift @@ -682,18 +682,24 @@ import UIKit /// - note: この関数をユーティリティとして用いてはいけない。 func userMovedCursor(count: Int) -> [ActionType] { debug("userによるカーソル移動を検知、今の位置は\(composingText.convertTargetCursorPosition)、動かしたオフセットは\(count)") - if composingText.isEmpty { + // 選択しているテキストがある場合はリザルトバーを表示する + if self.isSelected { + // リザルトバーを表示する + return [.setCursorBar(.off), .setTabBar(.off)] + } + // 入力テキストなし + if self.composingText.isEmpty { // 入力がない場合はreturnしておかないと、入力していない時にカーソルを動かせなくなってしまう。 return [.setCursorBar(.on)] } - let actualCount = composingText.moveCursorFromCursorPosition(count: count) - self.previousSystemOperation = self.displayedTextManager.updateComposingText(composingText: self.composingText, userMovedCount: count, adjustedMovedCount: actualCount) ? .moveCursor : nil - setResult() // ライブ変換有効 if liveConversionEnabled { return [.setCursorBar(.on)] } - return [] + let actualCount = composingText.moveCursorFromCursorPosition(count: count) + self.previousSystemOperation = self.displayedTextManager.updateComposingText(composingText: self.composingText, userMovedCount: count, adjustedMovedCount: actualCount) ? .moveCursor : nil + setResult() + return [.setCursorBar(.off), .setTabBar(.off)] } /// ユーザがキーボードを経由せずカットした場合の処理 From bbaa4a3ea5dff3c3bd0d23fe9e175d3357433d63 Mon Sep 17 00:00:00 2001 From: ensan-hcl Date: Tue, 17 Oct 2023 16:04:11 +0900 Subject: [PATCH 11/43] =?UTF-8?q?=E9=81=B8=E6=8A=9E=E7=8A=B6=E6=85=8B?= =?UTF-8?q?=E3=81=8C=E3=81=82=E3=82=8B=E5=A0=B4=E5=90=88=E3=81=AF=E8=A7=A3?= =?UTF-8?q?=E9=99=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Keyboard/Display/KeyboardActionManager.swift | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Keyboard/Display/KeyboardActionManager.swift b/Keyboard/Display/KeyboardActionManager.swift index 9d03b8e2..5a93fd69 100644 --- a/Keyboard/Display/KeyboardActionManager.swift +++ b/Keyboard/Display/KeyboardActionManager.swift @@ -523,6 +523,8 @@ import SwiftUtils if isSelected { debug("user operation id: 0", a_center) self.inputManager.userSelectedText(text: a_center) + // barStateの更新 + variableStates.barState = .none return } From 091fd3c88f9c4682711c039dd9cc66b61945cf37 Mon Sep 17 00:00:00 2001 From: ensan-hcl Date: Tue, 17 Oct 2023 16:44:57 +0900 Subject: [PATCH 12/43] =?UTF-8?q?feat:=20=E6=93=8D=E4=BD=9C=E3=81=8C?= =?UTF-8?q?=E3=81=AA=E3=81=84=E5=A0=B4=E5=90=88=E3=81=AB=E8=87=AA=E5=8B=95?= =?UTF-8?q?=E3=81=A7=E3=82=AB=E3=83=BC=E3=82=BD=E3=83=AB=E3=83=90=E3=83=BC?= =?UTF-8?q?=E3=82=92=E9=9D=9E=E8=A1=A8=E7=A4=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../View/KeyboardBar/KeyboardBarView.swift | 33 ++++++++++++++++--- 1 file changed, 29 insertions(+), 4 deletions(-) diff --git a/AzooKeyCore/Sources/KeyboardViews/View/KeyboardBar/KeyboardBarView.swift b/AzooKeyCore/Sources/KeyboardViews/View/KeyboardBar/KeyboardBarView.swift index 45c40db3..0e7fcd99 100644 --- a/AzooKeyCore/Sources/KeyboardViews/View/KeyboardBar/KeyboardBarView.swift +++ b/AzooKeyCore/Sources/KeyboardViews/View/KeyboardBar/KeyboardBarView.swift @@ -15,6 +15,9 @@ struct KeyboardBarView: Vie @EnvironmentObject private var variableStates: VariableStates @Binding private var isResultViewExpanded: Bool @Environment(Extension.Theme.self) private var theme + // CursorBarは操作がない場合に非表示にする。これをハンドルするためのタスク + @State private var dismissTask: Task<(), any Error>? = nil + private var useReflectStyleCursorBar: Bool { Extension.SettingProvider.useSliderStyleCursorBar } @@ -26,10 +29,20 @@ struct KeyboardBarView: Vie var body: some View { switch variableStates.barState { case .cursor: - if useReflectStyleCursorBar { - ReflectStyleCursorBar() - } else { - SliderStyleCursorBar() + Group { + if useReflectStyleCursorBar { + ReflectStyleCursorBar() + } else { + SliderStyleCursorBar() + } + } + .onAppear { + // 表示したタイミングでdismissTaskを開始 + self.restartCursorBarDismissTask() + } + .onChange(of: variableStates.textChangedCount) { _ in + // カーソルが動くたびにrestart + self.restartCursorBarDismissTask() } case .tab: let tabBarData = (try? variableStates.tabManager.config.custardManager.tabbar(identifier: 0)) ?? .default @@ -43,6 +56,18 @@ struct KeyboardBarView: Vie } } } + + private func restartCursorBarDismissTask() { + self.dismissTask?.cancel() + self.dismissTask = Task { + // 10秒待つ + try await Task.sleep(nanoseconds: 10_000_000_000) + try Task.checkCancellation() + withAnimation { + variableStates.barState = .none + } + } + } } @MainActor From 404d0523c51a8abbe1d2b3ca72c8eeeb8938a196 Mon Sep 17 00:00:00 2001 From: ensan-hcl Date: Tue, 17 Oct 2023 22:11:15 +0900 Subject: [PATCH 13/43] =?UTF-8?q?=E3=82=AB=E3=83=BC=E3=82=BD=E3=83=AB?= =?UTF-8?q?=E3=83=90=E3=83=BC=E3=81=AB=E8=A1=A8=E7=A4=BA=E3=81=95=E3=82=8C?= =?UTF-8?q?=E3=82=8B=E6=96=87=E5=AD=97=E3=81=8C=E6=9B=B4=E6=96=B0=E3=81=95?= =?UTF-8?q?=E3=82=8C=E3=81=AA=E3=81=8F=E3=81=AA=E3=82=8B=E5=95=8F=E9=A1=8C?= =?UTF-8?q?=E3=82=92=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../KeyboardViews/View/KeyboardBar/ReflectStyleCursorBar.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/AzooKeyCore/Sources/KeyboardViews/View/KeyboardBar/ReflectStyleCursorBar.swift b/AzooKeyCore/Sources/KeyboardViews/View/KeyboardBar/ReflectStyleCursorBar.swift index 52aa5e74..a730e49a 100644 --- a/AzooKeyCore/Sources/KeyboardViews/View/KeyboardBar/ReflectStyleCursorBar.swift +++ b/AzooKeyCore/Sources/KeyboardViews/View/KeyboardBar/ReflectStyleCursorBar.swift @@ -10,7 +10,7 @@ import SwiftUI import SwiftUIUtils import SwiftUtils -struct SliderStyleCursorBarState { +struct SliderStyleCursorBarState: Equatable { private(set) var displayLeftIndex = 0 private(set) var displayRightIndex = 0 fileprivate var line: [String] = [] From 707104825cd69a2ce5e04e98e2137516a248f1a1 Mon Sep 17 00:00:00 2001 From: ensan-hcl Date: Wed, 18 Oct 2023 09:57:11 +0900 Subject: [PATCH 14/43] =?UTF-8?q?TemporalMessageView=E3=81=8C=E6=B6=88?= =?UTF-8?q?=E3=81=88=E3=81=AA=E3=81=84=E3=81=93=E3=81=A8=E3=81=8C=E3=81=82?= =?UTF-8?q?=E3=82=8B=E5=95=8F=E9=A1=8C=E3=81=AB=E5=AF=BE=E5=87=A6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../KeyboardViews/TemporalMessage.swift | 4 +-- .../View/Components/TemporalMessageView.swift | 34 +++++++++++++------ .../KeyboardViews/View/KeyboardView.swift | 10 +++--- 3 files changed, 30 insertions(+), 18 deletions(-) diff --git a/AzooKeyCore/Sources/KeyboardViews/TemporalMessage.swift b/AzooKeyCore/Sources/KeyboardViews/TemporalMessage.swift index cf24665d..3e0f883e 100644 --- a/AzooKeyCore/Sources/KeyboardViews/TemporalMessage.swift +++ b/AzooKeyCore/Sources/KeyboardViews/TemporalMessage.swift @@ -7,7 +7,7 @@ import struct SwiftUI.LocalizedStringKey -public enum TemporalMessage { +public enum TemporalMessage: Sendable { case doneForgetCandidate case doneReportWrongConversion case failedReportWrongConversion @@ -23,7 +23,7 @@ public enum TemporalMessage { } } - public enum DismissCondition { + public enum DismissCondition: Sendable { case auto case ok } diff --git a/AzooKeyCore/Sources/KeyboardViews/View/Components/TemporalMessageView.swift b/AzooKeyCore/Sources/KeyboardViews/View/Components/TemporalMessageView.swift index e84072be..90342214 100644 --- a/AzooKeyCore/Sources/KeyboardViews/View/Components/TemporalMessageView.swift +++ b/AzooKeyCore/Sources/KeyboardViews/View/Components/TemporalMessageView.swift @@ -10,11 +10,15 @@ import Foundation import SwiftUI struct TemporalMessageView: View { - let message: TemporalMessage - let onDismiss: () -> Void - @EnvironmentObject private var variableStates: VariableStates - @Environment(\.userActionManager) private var action + init(message: TemporalMessage, isPresented: Binding) { + self.message = message + self._isPresented = isPresented + } + + private let message: TemporalMessage + @Binding private var isPresented: Bool + @MainActor @ViewBuilder private var core: some View { switch message.dismissCondition { @@ -22,19 +26,17 @@ struct TemporalMessageView: View { Text(message.title) .bold() .foregroundStyle(.black) - .onAppear { - Task { - // 1.5秒待機してからdismissを実行する - try await Task.sleep(nanoseconds: 1_500_000_000) - self.onDismiss() - } + .task { + // 1.5秒待機してからdismissを実行する + try? await Task.sleep(nanoseconds: 1_500_000_000) + self.dismiss() } case .ok: VStack { Text(message.title) .bold() .foregroundStyle(.black) - Button("OK", action: onDismiss) + Button("OK", action: self.dismiss) } } } @@ -51,4 +53,14 @@ struct TemporalMessageView: View { Color.black.opacity(0.5) } } + + private func dismiss() { + withAnimation(.easeIn) { + self.isPresented = false + } + } +} + +#Preview { + TemporalMessageView(message: .doneReportWrongConversion, isPresented: .init(get: { true }, set: { _ in })) } diff --git a/AzooKeyCore/Sources/KeyboardViews/View/KeyboardView.swift b/AzooKeyCore/Sources/KeyboardViews/View/KeyboardView.swift index 246d5d7f..59a03ad4 100644 --- a/AzooKeyCore/Sources/KeyboardViews/View/KeyboardView.swift +++ b/AzooKeyCore/Sources/KeyboardViews/View/KeyboardView.swift @@ -78,11 +78,11 @@ public struct KeyboardView: } } if showMessage, let message = variableStates.temporalMessage { - TemporalMessageView(message: message) { - withAnimation(.easeIn) { - variableStates.temporalMessage = nil - } - } + let isPresented = Binding( + get: { variableStates.temporalMessage != nil }, + set: { if !$0 {variableStates.temporalMessage = nil} } + ) + TemporalMessageView(message: message, isPresented: isPresented) } } .frame(height: Design.keyboardScreenHeight(upsideComponent: variableStates.upsideComponent, orientation: variableStates.keyboardOrientation)) From d197a019b4b23211aaa3f575253f63e0ddf2d542 Mon Sep 17 00:00:00 2001 From: ensan-hcl Date: Wed, 18 Oct 2023 13:50:08 +0900 Subject: [PATCH 15/43] =?UTF-8?q?Concurrency=20related=20warnings=E3=82=92?= =?UTF-8?q?=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- AzooKeyCore/Sources/KeyboardThemes/ThemeColor.swift | 2 +- .../KeyboardViews/View/SpecialTabs/ClipboardHistoryTab.swift | 3 +-- MainApp/Customize/ManageCustardView.swift | 2 -- MainApp/General/CancelableEditor.swift | 2 +- MainApp/General/DraggableView.swift | 3 ++- MainApp/Setting/Template/TemplateEditingView.swift | 3 +++ 6 files changed, 8 insertions(+), 7 deletions(-) diff --git a/AzooKeyCore/Sources/KeyboardThemes/ThemeColor.swift b/AzooKeyCore/Sources/KeyboardThemes/ThemeColor.swift index c63c5ce0..c3ef2be6 100644 --- a/AzooKeyCore/Sources/KeyboardThemes/ThemeColor.swift +++ b/AzooKeyCore/Sources/KeyboardThemes/ThemeColor.swift @@ -7,7 +7,7 @@ // import Foundation -@preconcurrency import SwiftUI +import SwiftUI public enum ThemeColor: Sendable { case color(Color) diff --git a/AzooKeyCore/Sources/KeyboardViews/View/SpecialTabs/ClipboardHistoryTab.swift b/AzooKeyCore/Sources/KeyboardViews/View/SpecialTabs/ClipboardHistoryTab.swift index be77d381..25c22481 100644 --- a/AzooKeyCore/Sources/KeyboardViews/View/SpecialTabs/ClipboardHistoryTab.swift +++ b/AzooKeyCore/Sources/KeyboardViews/View/SpecialTabs/ClipboardHistoryTab.swift @@ -6,6 +6,7 @@ // Copyright © 2023 ensan. All rights reserved. // +@preconcurrency import LinkPresentation import SwiftUI import SwiftUIUtils import SwiftUtils @@ -254,8 +255,6 @@ struct ClipboardHistoryTab: } } -import LinkPresentation - private struct RichLinkView: UIViewRepresentable { class UIViewType: LPLinkView { override var intrinsicContentSize: CGSize { CGSize(width: 0, height: super.intrinsicContentSize.height) } diff --git a/MainApp/Customize/ManageCustardView.swift b/MainApp/Customize/ManageCustardView.swift index e23fb87d..83f60a1d 100644 --- a/MainApp/Customize/ManageCustardView.swift +++ b/MainApp/Customize/ManageCustardView.swift @@ -113,7 +113,6 @@ private final class ImportedCustardData: ObservableObject { } } - @MainActor private func downloadAsync(from url: URL) async { do { self.processState = .getFile @@ -356,7 +355,6 @@ struct ManageCustardView: View { guard let url = URL(string: "https://azooKey.netlify.com/static/custard/all") else { return } - let request = URLRequest(url: url) Task { let result = try await URLSession.shared.data(from: url).0 let decoder = JSONDecoder() diff --git a/MainApp/General/CancelableEditor.swift b/MainApp/General/CancelableEditor.swift index 44684cc5..0613a640 100644 --- a/MainApp/General/CancelableEditor.swift +++ b/MainApp/General/CancelableEditor.swift @@ -10,6 +10,6 @@ import SwiftUI protocol CancelableEditor: View { associatedtype EditTarget - var base: EditTarget { get } + @MainActor var base: EditTarget { get } @MainActor func cancel() } diff --git a/MainApp/General/DraggableView.swift b/MainApp/General/DraggableView.swift index 6e924914..cac59d6e 100644 --- a/MainApp/General/DraggableView.swift +++ b/MainApp/General/DraggableView.swift @@ -44,7 +44,7 @@ struct DraggableView) { self._template = template if let template = template.wrappedValue.literal as? DateTemplateLiteral { @@ -346,6 +348,7 @@ struct DateTemplateLiteralSettingView: View { return f }() + @MainActor private func update() { DispatchQueue.main.async { if formatSelection == "カスタム"{ From 8da5db1de9284abc33e290fb80cc3d669caedc69 Mon Sep 17 00:00:00 2001 From: ensan-hcl Date: Thu, 19 Oct 2023 00:56:24 +0900 Subject: [PATCH 16/43] =?UTF-8?q?drawingGroup()=E3=81=8C=E5=8E=9F=E5=9B=A0?= =?UTF-8?q?=E3=81=A0=E3=81=A3=E3=81=9F=E3=81=AE=E3=81=A7=E5=89=8A=E9=99=A4?= =?UTF-8?q?=E3=81=97=E3=80=81state=E3=81=AE=E7=AE=A1=E7=90=86=E3=81=AE?= =?UTF-8?q?=E6=A7=8B=E9=80=A0=E3=82=92=E5=A4=89=E6=9B=B4=E3=81=97=E3=81=9F?= =?UTF-8?q?=E3=80=82=E5=90=88=E3=82=8F=E3=81=9B=E3=81=A6=E3=80=81View?= =?UTF-8?q?=E3=81=8C=E3=82=AC=E3=83=81=E3=83=A3=E3=82=AC=E3=83=81=E3=83=A3?= =?UTF-8?q?=E3=81=A8=E5=8B=95=E3=81=8F=E5=95=8F=E9=A1=8C=E3=82=92=E8=A7=A3?= =?UTF-8?q?=E6=B1=BA=E3=81=97=E3=80=81=E3=82=AB=E3=83=BC=E3=82=BD=E3=83=AB?= =?UTF-8?q?=E3=83=90=E3=83=BC=E3=81=AE=E8=87=AA=E5=8B=95=E8=A1=A8=E7=A4=BA?= =?UTF-8?q?=E3=81=AE=E3=83=90=E3=82=B0=E3=82=92=E7=9B=B4=E3=81=97=E3=81=9F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../KeyboardViews/VariableStates.swift | 19 +++--- .../KeyboardBar/ReflectStyleCursorBar.swift | 59 ++++++++++++++----- Keyboard/Display/InputManager.swift | 9 +++ Keyboard/Display/KeyboardActionManager.swift | 6 +- 4 files changed, 64 insertions(+), 29 deletions(-) diff --git a/AzooKeyCore/Sources/KeyboardViews/VariableStates.swift b/AzooKeyCore/Sources/KeyboardViews/VariableStates.swift index 03a6806a..11caf36f 100644 --- a/AzooKeyCore/Sources/KeyboardViews/VariableStates.swift +++ b/AzooKeyCore/Sources/KeyboardViews/VariableStates.swift @@ -162,19 +162,19 @@ public final class VariableStates: ObservableObject { @Published public var undoAction: UndoAction? - @Published var moveCursorBarState = SliderStyleCursorBarState() - - @Published private(set) var leftSideText: String = "" - @Published private(set) var centerText: String = "" - @Published private(set) var rightSideText: String = "" + struct SurroundingText: Equatable, Hashable, Sendable { + var leftSideText: String = "" + var centerText: String = "" + var rightSideText: String = "" + } + @Published private(set) var surroundingText = SurroundingText() @Published public var temporalMessage: TemporalMessage? public func setSurroundingText(leftSide: String, center: String, rightSide: String) { - self.leftSideText = leftSide - self.centerText = center - self.rightSideText = rightSide - self.moveCursorBarState.updateLine(leftText: leftSide + center, rightText: rightSide) + self.surroundingText.leftSideText = leftSide + self.surroundingText.centerText = center + self.surroundingText.rightSideText = rightSide } @MainActor public func setResizingMode(_ state: ResizingState) { @@ -197,7 +197,6 @@ public final class VariableStates: ObservableObject { @MainActor public func initialize() { self.tabManager.initialize(variableStates: self) - self.moveCursorBarState.clear() } @MainActor public func closeKeyboard() { diff --git a/AzooKeyCore/Sources/KeyboardViews/View/KeyboardBar/ReflectStyleCursorBar.swift b/AzooKeyCore/Sources/KeyboardViews/View/KeyboardBar/ReflectStyleCursorBar.swift index a730e49a..8d4d7baf 100644 --- a/AzooKeyCore/Sources/KeyboardViews/View/KeyboardBar/ReflectStyleCursorBar.swift +++ b/AzooKeyCore/Sources/KeyboardViews/View/KeyboardBar/ReflectStyleCursorBar.swift @@ -10,7 +10,7 @@ import SwiftUI import SwiftUIUtils import SwiftUtils -struct SliderStyleCursorBarState: Equatable { +private struct CursorBarState: Equatable, Hashable, Sendable { private(set) var displayLeftIndex = 0 private(set) var displayRightIndex = 0 fileprivate var line: [String] = [] @@ -25,10 +25,10 @@ struct SliderStyleCursorBarState: Equatable { } mutating func updateLine(leftText: String, rightText: String) { - debug("updateLine", leftText, rightText, itemCount, line) + debug("CursorBarState.updateLine", leftText, rightText, itemCount, line) var left = leftText.map {String($0)} - if left.first == "\n" { - left.removeFirst() + if let index = left.firstIndex(of: "\n"), index != left.endIndex - 1 { + left.removeFirst(index + 1) } self.line = left + rightText.map {String($0)} + ["⏎"] self.displayLeftIndex = left.count - itemCount / 2 @@ -43,6 +43,10 @@ struct SliderStyleCursorBarState: Equatable { } @MainActor mutating fileprivate func move(_ count: Int, actionManager: some UserActionManager, variableStates: VariableStates) { + if centerIndex + count < -1 || line.count < centerIndex + count { + debug("CursorBarState.move rejected", centerIndex, count, line) + return + } displayLeftIndex += count displayRightIndex += count actionManager.registerAction(.moveCursor(count), variableStates: variableStates) @@ -67,7 +71,6 @@ struct SliderStyleCursorBarState: Equatable { } } -@MainActor struct ReflectStyleCursorBar: View { init() {} @@ -75,23 +78,30 @@ struct ReflectStyleCursorBar= 15 { - variableStates.moveCursorBarState.move(1, actionManager: self.action, variableStates: variableStates) + cursorBarState.move(1, actionManager: self.action, variableStates: variableStates) count -= 15 } if count <= -15 { - variableStates.moveCursorBarState.move(-1, actionManager: self.action, variableStates: variableStates) + cursorBarState.move(-1, actionManager: self.action, variableStates: variableStates) count += 15 } swipeGestureState = .moving(l1: value.location, l2: l1, l3: l2, count: count) @@ -159,9 +169,9 @@ struct ReflectStyleCursorBar [ActionType] { + if self.composingText.isEmpty { + return [.setCursorBar(.on)] + } + self.stopComposition() + return [] + } + /// ユーザがキーボードを経由せずカットした場合の処理 func userCutText(text: String) { self.stopComposition() diff --git a/Keyboard/Display/KeyboardActionManager.swift b/Keyboard/Display/KeyboardActionManager.swift index 7f9dbae4..fdbc4ef8 100644 --- a/Keyboard/Display/KeyboardActionManager.swift +++ b/Keyboard/Display/KeyboardActionManager.swift @@ -524,7 +524,6 @@ import SwiftUtils /// 何かが変化した後に状態を比較し、どのような変化が起こったのか判断する関数。 override func notifySomethingDidChange(a_left: String, a_center: String, a_right: String, variableStates: VariableStates) { defer { - // moveCursorBarStateの更新 variableStates.setSurroundingText(leftSide: a_left, center: a_center, rightSide: a_right) // エンターキーの状態の更新 variableStates.setEnterKeyState(self.inputManager.getEnterKeyState()) @@ -669,9 +668,10 @@ import SwiftUtils return } - // 上記のどれにも引っかからず、なおかつテキスト全体が変更された場合 + // 上記のどれにも引っかからず、なおかつテキスト全体が変更された場合→ユーザがカーソルをジャンプした debug("user operation id: 10, \((a_left, a_center, a_right)), \((b_left, b_center, b_right))") - self.inputManager.stopComposition() + let actions = self.inputManager.userJumpedCursor() + self.registerActions(actions, variableStates: variableStates) } private func hideLearningMemory() { From 58ba1fe657272ea9bf2fc131830dc17c44e2b39a Mon Sep 17 00:00:00 2001 From: ensan-hcl Date: Thu, 19 Oct 2023 01:02:24 +0900 Subject: [PATCH 17/43] =?UTF-8?q?MainActor=E3=81=A7=E5=AE=9F=E8=A1=8C?= =?UTF-8?q?=E3=81=99=E3=82=8B=E5=87=A6=E7=90=86=E3=81=A8=E3=81=9D=E3=81=86?= =?UTF-8?q?=E3=81=A7=E3=81=AA=E3=81=84=E5=87=A6=E7=90=86=E3=82=92=E5=88=86?= =?UTF-8?q?=E5=88=A5=E3=81=97=E3=81=9F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../KeyboardViews/KeyboardFeedback.swift | 67 ++++++++++--------- 1 file changed, 36 insertions(+), 31 deletions(-) diff --git a/AzooKeyCore/Sources/KeyboardViews/KeyboardFeedback.swift b/AzooKeyCore/Sources/KeyboardViews/KeyboardFeedback.swift index e18bece5..94b212b1 100644 --- a/AzooKeyCore/Sources/KeyboardViews/KeyboardFeedback.swift +++ b/AzooKeyCore/Sources/KeyboardViews/KeyboardFeedback.swift @@ -7,22 +7,26 @@ // import func AudioToolbox.AudioServicesPlaySystemSound -import Foundation +import typealias AudioToolbox.SystemSoundID import class UIKit.UIImpactFeedbackGenerator /// フィードバックを返すためのツールセット -@MainActor public enum KeyboardFeedback { +public enum KeyboardFeedback { + @MainActor private static var enableSound: Bool { Extension.SettingProvider.enableSound } + @MainActor private static var requestedHaptics: Bool { Extension.SettingProvider.enableHaptics } + @MainActor private static var enableHaptics: Bool { SemiStaticStates.shared.hapticsAvailable && SemiStaticStates.shared.hasFullAccess && requestedHaptics } // FIXME: possibly too heavy - private static var generator: UIImpactFeedbackGenerator { UIImpactFeedbackGenerator(style: .light) } + @MainActor + private static var generator: UIImpactFeedbackGenerator { UIImpactFeedbackGenerator(style: .light) } // 使えそうな音 /* i @@ -42,53 +46,54 @@ import class UIKit.UIImpactFeedbackGenerator /// 入力を伴う操作を行う際にフィードバックを返します。 /// - Note: 押しはじめに鳴らす方が反応が良く感じます。 public static func click() { - if enableSound { - AudioServicesPlaySystemSound(1104) - } - if enableHaptics { - generator.impactOccurred(intensity: 0.7) - } + playSystemSound(1104) + impactOnMainActor(intensity: 0.7) } /// タブの移動、入力の確定、小仮名濁点化、カーソル移動などを伴う操作を行う際にフィードバックを返します。 /// - Note: 押しはじめに鳴らす方が反応が良く感じます。 public static func tabOrOtherKey() { - if enableSound { - AudioServicesPlaySystemSound(1156) - } - if enableHaptics { - generator.impactOccurred(intensity: 0.75) - } + playSystemSound(1156) + impactOnMainActor(intensity: 0.75) } /// 文字の削除などを伴う操作を行う際に音を鳴らします。 /// - Note: 押しはじめに鳴らす方が反応が良く感じます。 public static func delete() { - if enableSound { - AudioServicesPlaySystemSound(1155) - } - if enableHaptics { - generator.impactOccurred(intensity: 0.75) - } + playSystemSound(1155) + impactOnMainActor(intensity: 0.75) } /// 文字の一括削除の操作を行う際にフィードバックを返します。 public static func smoothDelete() { - if enableSound { - AudioServicesPlaySystemSound(1105) - } - if enableHaptics { - generator.impactOccurred(intensity: 0.8) - } + playSystemSound(1105) + impactOnMainActor(intensity: 0.8) } /// 操作のリセットを行うときにフィードバックを返します。 public static func reset() { - if enableSound { - AudioServicesPlaySystemSound(1533) + playSystemSound(1533) + impactOnMainActor(intensity: 1) + } + + /// systemSoundの再生のラッパー + /// - Note: `generator.impactOccurred`はMainActor上でのみ動作する + public static func impactOnMainActor(intensity: Double) { + Task { @MainActor in + if enableHaptics { + generator.impactOccurred(intensity: intensity) + } } - if enableHaptics { - generator.impactOccurred(intensity: 1) + } + + /// systemSoundの再生のラッパー + /// - Note: `AudioServicesPlaySystemSound`は非同期で呼び出さないと爆音が鳴ることがある + public static func playSystemSound(_ id: SystemSoundID) { + Task { + if await enableSound { + // 再生自体は非同期で実行される + AudioServicesPlaySystemSound(id) + } } } } From 113a115078b98a8b7190d0160382f902870145ed Mon Sep 17 00:00:00 2001 From: ensan-hcl Date: Thu, 19 Oct 2023 01:10:27 +0900 Subject: [PATCH 18/43] Avoid multiple initialization of UIImpactFeedbackGenerator --- AzooKeyCore/Sources/KeyboardViews/KeyboardFeedback.swift | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/AzooKeyCore/Sources/KeyboardViews/KeyboardFeedback.swift b/AzooKeyCore/Sources/KeyboardViews/KeyboardFeedback.swift index 94b212b1..6148cf69 100644 --- a/AzooKeyCore/Sources/KeyboardViews/KeyboardFeedback.swift +++ b/AzooKeyCore/Sources/KeyboardViews/KeyboardFeedback.swift @@ -10,6 +10,9 @@ import func AudioToolbox.AudioServicesPlaySystemSound import typealias AudioToolbox.SystemSoundID import class UIKit.UIImpactFeedbackGenerator +private enum UIImpactFeedbackGeneratorHolder { + @MainActor static let generator = UIImpactFeedbackGenerator(style: .light) +} /// フィードバックを返すためのツールセット public enum KeyboardFeedback { @MainActor @@ -24,9 +27,6 @@ public enum KeyboardFeedback Date: Thu, 19 Oct 2023 03:49:18 +0900 Subject: [PATCH 19/43] =?UTF-8?q?=E7=8F=BE=E7=8A=B6=E3=81=AE=E3=82=B3?= =?UTF-8?q?=E3=83=BC=E3=83=89=E3=82=92=E7=A7=BB=E6=A4=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 移植元とのバージョン違いによるエラー --- .../SuggestView/FlickSuggestView.swift | 225 ++++++++++++++---- 1 file changed, 179 insertions(+), 46 deletions(-) diff --git a/AzooKeyCore/Sources/KeyboardViews/View/FlickKeyboard/SuggestView/FlickSuggestView.swift b/AzooKeyCore/Sources/KeyboardViews/View/FlickKeyboard/SuggestView/FlickSuggestView.swift index 8cb23cd4..6d98bcb9 100644 --- a/AzooKeyCore/Sources/KeyboardViews/View/FlickKeyboard/SuggestView/FlickSuggestView.swift +++ b/AzooKeyCore/Sources/KeyboardViews/View/FlickKeyboard/SuggestView/FlickSuggestView.swift @@ -18,70 +18,203 @@ struct FlickSuggestView: Vi private let suggestType: FlickSuggestType private let tabDesign: TabDependentDesign private let size: CGSize - + init(model: any FlickKeyModelProtocol, tabDesign: TabDependentDesign, size: CGSize, suggestType: FlickSuggestType) { self.model = model self.tabDesign = tabDesign self.size = size self.suggestType = suggestType } - - private func getSuggestView(for model: FlickedKeyModel, isHidden: Bool, isPointed: Bool = false) -> some View { - // 着せ替えが有効の場合、サジェストの背景色はwhiteにする。 + + private func getSuggestView(for _: FlickedKeyModel, isHidden: Bool, isPointed: Bool = false) -> some View { + // ポインテッド時の色を定義 var pointedColor: Color { - theme != Extension.ThemeExtension.default(layout: .flick) ? .white : .systemGray4 + theme != Extension.ThemeExtension.default(layout: .flick) ? .white : .white } + // ポインテッドでない時の色を定義 var unpointedColor: Color { theme != Extension.ThemeExtension.default(layout: .flick) ? .white : .systemGray5 } - + + // 現在の状態に基づいて色を選択 let color = isPointed ? pointedColor : unpointedColor - return RoundedRectangle(cornerRadius: 5.0) - .strokeAndFill(fillContent: color, strokeContent: theme.borderColor.color, lineWidth: theme.borderWidth) - .frame(width: size.width, height: size.height) - .overlay { - // ラベル - KeyLabel(model.labelType, width: size.width, textColor: theme.suggestLabelTextColor?.color) + let shape: any Shape + let paddings: [CGFloat] + let spacers: [CGFloat] + let sizeTimes: [CGFloat] + + switch direction { + case .top: + shape = RoundedPentagonTop() + paddings = [0, 0, 0.2, 0] + spacers = [0, 0, 0, 0.25] + sizeTimes = [1.2, 1.5] + case .left: + shape = RoundedPentagonLeft() + paddings = [0, 0, 0, 0.3] + spacers = [0, 0, 0.1, 0] + sizeTimes = [1.5, 1.2] + case .right: + shape = RoundedPentagonRight() + paddings = [0, 0.3, 0, 0] + spacers = [0, 0.1, 0, 0] + sizeTimes = [1.5, 1.2] + case .bottom: + shape = RoundedPentagonBottom() + paddings = [0.2, 0, 0, 0] + spacers = [0.25, 0, 0, 0] + sizeTimes = [1.2, 1.5] + } + + return VStack { + Spacer().frame(height: size.height * spacers[0]) + HStack { + Spacer().frame(width: size.width * spacers[1]) + AnyView(shape + .strokeAndFill(fillContent: color, strokeContent: theme.borderColor.color, lineWidth: theme.borderWidth)) + .frame(width: size.width * sizeTimes[0], height: size.height * sizeTimes[1]) + .shadow(color: Color.gray, radius: 10, x: 5, y: 5) + .overlay(self.label(width: size.width, theme: theme, extension: Extension.self).padding(EdgeInsets(top: size.width * paddings[0], leading: size.width * paddings[1], bottom: size.width * paddings[2], trailing: size.width * paddings[3]))) + .allowsHitTesting(false) + .opacity(isHidden ? 0 : 1) + Spacer().frame(width: size.width * spacers[2]) } - .allowsHitTesting(false) - .opacity(isHidden ? 0 : 1) - } - - /// その方向にViewの表示が必要な場合はサジェストのViewを、不要な場合は透明なViewを返す。 - @ViewBuilder private func getSuggestViewIfNecessary(direction: FlickDirection) -> some View { - switch self.suggestType { - case .all: - if let model = self.model.flickKeys(variableStates: variableStates)[direction] { - getSuggestView(for: model, isHidden: false) - } else { - getSuggestView(for: .empty, isHidden: true) + } + + /// その方向にViewの表示が必要な場合はサジェストのViewを、不要な場合は透明なViewを返す。 + @ViewBuilder private func getSuggestViewIfNecessary(direction: FlickDirection) -> some View { + switch suggestType { + case .all: + if let model = model.flickKeys(variableStates: variableStates)[direction] { + getSuggestView(for: model, isHidden: false) + } else { + getSuggestView(for: .empty, isHidden: true) + } + case .flick(let targetDirection): + if targetDirection == direction, let model = model.flickKeys(variableStates: variableStates)[direction] { + getSuggestView(for: model, isHidden: false, isPointed: true) + } else { + getSuggestView(for: .empty, isHidden: true) + } } - case .flick(let targetDirection): - if targetDirection == direction, let model = self.model.flickKeys(variableStates: variableStates)[direction] { - getSuggestView(for: model, isHidden: false, isPointed: true) - } else { - getSuggestView(for: .empty, isHidden: true) + } + + var body: some View { + VStack(spacing: tabDesign.verticalSpacing) { + self.getSuggestViewIfNecessary(direction: .top) + HStack(spacing: tabDesign.horizontalSpacing) { + self.getSuggestViewIfNecessary(direction: .left) + RoundedRectangle(cornerRadius: 5.0) + .strokeAndFill( + fillContent: theme.specialKeyFillColor.color, + strokeContent: theme.borderColor.color, + lineWidth: theme.borderWidth + ) + .frame(width: size.width, height: size.height) + self.getSuggestViewIfNecessary(direction: .right) + } + self.getSuggestViewIfNecessary(direction: .bottom) } + .frame(width: size.width, height: size.height) + .allowsHitTesting(false) } } - - var body: some View { - VStack(spacing: tabDesign.verticalSpacing) { - self.getSuggestViewIfNecessary(direction: .top) - HStack(spacing: tabDesign.horizontalSpacing) { - self.getSuggestViewIfNecessary(direction: .left) - RoundedRectangle(cornerRadius: 5.0) - .strokeAndFill( - fillContent: theme.specialKeyFillColor.color, - strokeContent: theme.borderColor.color, - lineWidth: theme.borderWidth - ) - .frame(width: size.width, height: size.height) - self.getSuggestViewIfNecessary(direction: .right) +} + +public extension Path { + mutating func addRoundedPentagon(using points: [CGPoint], cornerRadius: CGFloat = 5) { + guard points.count == 5 else { return } + + for i in 0 ..< 5 { + let currentPoint = points[i] + let nextPoint = points[(i + 1) % 5] + let prevPoint = i == 0 ? points.last! : points[i - 1] + + let directionFromPrev = CGVector(dx: currentPoint.x - prevPoint.x, dy: currentPoint.y - prevPoint.y).normalized + let directionToNext = CGVector(dx: nextPoint.x - currentPoint.x, dy: nextPoint.y - currentPoint.y).normalized + + let offsetFromCurrent1 = CGVector(dx: directionFromPrev.dx * cornerRadius, dy: directionFromPrev.dy * cornerRadius) + let offsetFromCurrent2 = CGVector(dx: directionToNext.dx * cornerRadius, dy: directionToNext.dy * cornerRadius) + + if i == 0 { + move(to: CGPoint(x: currentPoint.x - offsetFromCurrent1.dx, y: currentPoint.y - offsetFromCurrent1.dy)) + } else { + addLine(to: CGPoint(x: currentPoint.x - offsetFromCurrent1.dx, y: currentPoint.y - offsetFromCurrent1.dy)) } - self.getSuggestViewIfNecessary(direction: .bottom) + + addQuadCurve(to: CGPoint(x: currentPoint.x + offsetFromCurrent2.dx, y: currentPoint.y + offsetFromCurrent2.dy), control: currentPoint) } - .frame(width: size.width, height: size.height) - .allowsHitTesting(false) + + closeSubpath() + } +} + +extension CGVector { + var length: CGFloat { + return sqrt(dx * dx + dy * dy) + } + + var normalized: CGVector { + return CGVector(dx: dx / length, dy: dy / length) + } +} + +struct RoundedPentagonBottom: Shape { + func path(in rect: CGRect) -> Path { + var path = Path() + let points = [ + CGPoint(x: rect.width / 2, y: 0), + CGPoint(x: 0, y: rect.height / 3), + CGPoint(x: 0, y: rect.height), + CGPoint(x: rect.width, y: rect.height), + CGPoint(x: rect.width, y: rect.height / 3) + ] + path.addRoundedPentagon(using: points) + return path + } +} + +struct RoundedPentagonLeft: Shape { + func path(in rect: CGRect) -> Path { + var path = Path() + let points = [ + CGPoint(x: 0, y: 0), + CGPoint(x: rect.width * 2 / 3, y: 0), + CGPoint(x: rect.width, y: rect.height / 2), + CGPoint(x: rect.width * 2 / 3, y: rect.height), + CGPoint(x: 0, y: rect.height) + ] + path.addRoundedPentagon(using: points) + return path + } +} + +struct RoundedPentagonRight: Shape { + func path(in rect: CGRect) -> Path { + var path = Path() + let points = [ + CGPoint(x: rect.width / 3, y: 0), + CGPoint(x: 0, y: rect.height / 2), + CGPoint(x: rect.width / 3, y: rect.height), + CGPoint(x: rect.width, y: rect.height), + CGPoint(x: rect.width, y: 0) + ] + path.addRoundedPentagon(using: points) + return path + } +} + +struct RoundedPentagonTop: Shape { + func path(in rect: CGRect) -> Path { + var path = Path() + let points = [ + CGPoint(x: rect.width / 2, y: rect.height), + CGPoint(x: rect.width, y: 2 * rect.height / 3), + CGPoint(x: rect.width, y: 0), + CGPoint(x: 0, y: 0), + CGPoint(x: 0, y: 2 * rect.height / 3) + ] + path.addRoundedPentagon(using: points) + return path } } From 0f02934c681042fc81043a0907d19eba7d27e333 Mon Sep 17 00:00:00 2001 From: ensan-hcl Date: Thu, 19 Oct 2023 23:48:14 +0900 Subject: [PATCH 20/43] =?UTF-8?q?=E3=83=93=E3=83=AB=E3=83=89=E3=82=92?= =?UTF-8?q?=E9=80=9A=E3=81=97=E3=81=9F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../SuggestView/FlickSuggestView.swift | 88 ++++++++++--------- 1 file changed, 48 insertions(+), 40 deletions(-) diff --git a/AzooKeyCore/Sources/KeyboardViews/View/FlickKeyboard/SuggestView/FlickSuggestView.swift b/AzooKeyCore/Sources/KeyboardViews/View/FlickKeyboard/SuggestView/FlickSuggestView.swift index 6d98bcb9..d1bffd32 100644 --- a/AzooKeyCore/Sources/KeyboardViews/View/FlickKeyboard/SuggestView/FlickSuggestView.swift +++ b/AzooKeyCore/Sources/KeyboardViews/View/FlickKeyboard/SuggestView/FlickSuggestView.swift @@ -26,7 +26,7 @@ struct FlickSuggestView: Vi self.suggestType = suggestType } - private func getSuggestView(for _: FlickedKeyModel, isHidden: Bool, isPointed: Bool = false) -> some View { + private func getSuggestView(for model: FlickedKeyModel, direction: FlickDirection, isHidden: Bool, isPointed: Bool = false) -> some View { // ポインテッド時の色を定義 var pointedColor: Color { theme != Extension.ThemeExtension.default(layout: .flick) ? .white : .white @@ -72,53 +72,61 @@ struct FlickSuggestView: Vi Spacer().frame(width: size.width * spacers[1]) AnyView(shape .strokeAndFill(fillContent: color, strokeContent: theme.borderColor.color, lineWidth: theme.borderWidth)) - .frame(width: size.width * sizeTimes[0], height: size.height * sizeTimes[1]) - .shadow(color: Color.gray, radius: 10, x: 5, y: 5) - .overlay(self.label(width: size.width, theme: theme, extension: Extension.self).padding(EdgeInsets(top: size.width * paddings[0], leading: size.width * paddings[1], bottom: size.width * paddings[2], trailing: size.width * paddings[3]))) - .allowsHitTesting(false) - .opacity(isHidden ? 0 : 1) + .frame(width: size.width * sizeTimes[0], height: size.height * sizeTimes[1]) + .shadow(color: Color.gray, radius: 10, x: 5, y: 5) + .overlay { + KeyLabel(model.labelType, width: size.width, textColor: theme.suggestLabelTextColor?.color) + .padding(EdgeInsets( + top: size.width * paddings[0], + leading: size.width * paddings[1], + bottom: size.width * paddings[2], + trailing: size.width * paddings[3] + )) + } + .allowsHitTesting(false) + .opacity(isHidden ? 0 : 1) Spacer().frame(width: size.width * spacers[2]) } } - - /// その方向にViewの表示が必要な場合はサジェストのViewを、不要な場合は透明なViewを返す。 - @ViewBuilder private func getSuggestViewIfNecessary(direction: FlickDirection) -> some View { - switch suggestType { - case .all: - if let model = model.flickKeys(variableStates: variableStates)[direction] { - getSuggestView(for: model, isHidden: false) - } else { - getSuggestView(for: .empty, isHidden: true) - } - case .flick(let targetDirection): - if targetDirection == direction, let model = model.flickKeys(variableStates: variableStates)[direction] { - getSuggestView(for: model, isHidden: false, isPointed: true) - } else { - getSuggestView(for: .empty, isHidden: true) - } + } + /// その方向にViewの表示が必要な場合はサジェストのViewを、不要な場合は透明なViewを返す。 + @ViewBuilder private func getSuggestViewIfNecessary(direction: FlickDirection) -> some View { + switch suggestType { + case .all: + if let model = self.model.flickKeys(variableStates: variableStates)[direction] { + getSuggestView(for: model, direction: direction, isHidden: false) + } else { + getSuggestView(for: .empty, direction: direction, isHidden: true) + } + case .flick(let targetDirection): + if targetDirection == direction, let model = self.model.flickKeys(variableStates: variableStates)[direction] { + getSuggestView(for: model, direction: direction, isHidden: false, isPointed: true) + } else { + getSuggestView(for: .empty, direction: direction, isHidden: true) } } - - var body: some View { - VStack(spacing: tabDesign.verticalSpacing) { - self.getSuggestViewIfNecessary(direction: .top) - HStack(spacing: tabDesign.horizontalSpacing) { - self.getSuggestViewIfNecessary(direction: .left) - RoundedRectangle(cornerRadius: 5.0) - .strokeAndFill( - fillContent: theme.specialKeyFillColor.color, - strokeContent: theme.borderColor.color, - lineWidth: theme.borderWidth - ) - .frame(width: size.width, height: size.height) - self.getSuggestViewIfNecessary(direction: .right) - } - self.getSuggestViewIfNecessary(direction: .bottom) + } + + var body: some View { + VStack(spacing: tabDesign.verticalSpacing) { + self.getSuggestViewIfNecessary(direction: .top) + HStack(spacing: tabDesign.horizontalSpacing) { + self.getSuggestViewIfNecessary(direction: .left) + RoundedRectangle(cornerRadius: 5.0) + .strokeAndFill( + fillContent: theme.specialKeyFillColor.color, + strokeContent: theme.borderColor.color, + lineWidth: theme.borderWidth + ) + .frame(width: size.width, height: size.height) + self.getSuggestViewIfNecessary(direction: .right) } - .frame(width: size.width, height: size.height) - .allowsHitTesting(false) + self.getSuggestViewIfNecessary(direction: .bottom) } + .frame(width: size.width, height: size.height) + .allowsHitTesting(false) } + } public extension Path { From a37f8cbdc4e20ece5c4edc31b797685e9461b79a Mon Sep 17 00:00:00 2001 From: ensan-hcl Date: Thu, 19 Oct 2023 23:49:10 +0900 Subject: [PATCH 21/43] adjust access control --- .../FlickKeyboard/SuggestView/FlickSuggestView.swift | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/AzooKeyCore/Sources/KeyboardViews/View/FlickKeyboard/SuggestView/FlickSuggestView.swift b/AzooKeyCore/Sources/KeyboardViews/View/FlickKeyboard/SuggestView/FlickSuggestView.swift index d1bffd32..1819607e 100644 --- a/AzooKeyCore/Sources/KeyboardViews/View/FlickKeyboard/SuggestView/FlickSuggestView.swift +++ b/AzooKeyCore/Sources/KeyboardViews/View/FlickKeyboard/SuggestView/FlickSuggestView.swift @@ -129,7 +129,7 @@ struct FlickSuggestView: Vi } -public extension Path { +private extension Path { mutating func addRoundedPentagon(using points: [CGPoint], cornerRadius: CGFloat = 5) { guard points.count == 5 else { return } @@ -157,7 +157,7 @@ public extension Path { } } -extension CGVector { +private extension CGVector { var length: CGFloat { return sqrt(dx * dx + dy * dy) } @@ -167,7 +167,7 @@ extension CGVector { } } -struct RoundedPentagonBottom: Shape { +private struct RoundedPentagonBottom: Shape { func path(in rect: CGRect) -> Path { var path = Path() let points = [ @@ -182,7 +182,7 @@ struct RoundedPentagonBottom: Shape { } } -struct RoundedPentagonLeft: Shape { +private struct RoundedPentagonLeft: Shape { func path(in rect: CGRect) -> Path { var path = Path() let points = [ @@ -197,7 +197,7 @@ struct RoundedPentagonLeft: Shape { } } -struct RoundedPentagonRight: Shape { +private struct RoundedPentagonRight: Shape { func path(in rect: CGRect) -> Path { var path = Path() let points = [ @@ -212,7 +212,7 @@ struct RoundedPentagonRight: Shape { } } -struct RoundedPentagonTop: Shape { +private struct RoundedPentagonTop: Shape { func path(in rect: CGRect) -> Path { var path = Path() let points = [ From e10c07aa96e7be00e1d6691af43e80942609026f Mon Sep 17 00:00:00 2001 From: ensan-hcl Date: Thu, 19 Oct 2023 23:53:51 +0900 Subject: [PATCH 22/43] Add missing space --- .../View/FlickKeyboard/SuggestView/FlickSuggestView.swift | 1 + 1 file changed, 1 insertion(+) diff --git a/AzooKeyCore/Sources/KeyboardViews/View/FlickKeyboard/SuggestView/FlickSuggestView.swift b/AzooKeyCore/Sources/KeyboardViews/View/FlickKeyboard/SuggestView/FlickSuggestView.swift index 1819607e..d06963fe 100644 --- a/AzooKeyCore/Sources/KeyboardViews/View/FlickKeyboard/SuggestView/FlickSuggestView.swift +++ b/AzooKeyCore/Sources/KeyboardViews/View/FlickKeyboard/SuggestView/FlickSuggestView.swift @@ -87,6 +87,7 @@ struct FlickSuggestView: Vi .opacity(isHidden ? 0 : 1) Spacer().frame(width: size.width * spacers[2]) } + Spacer().frame(height: size.height * spacers[3]) } } /// その方向にViewの表示が必要な場合はサジェストのViewを、不要な場合は透明なViewを返す。 From 65adfd5ce88f9f87f24fb922ff44cbbe77ff04f6 Mon Sep 17 00:00:00 2001 From: ensan-hcl Date: Fri, 20 Oct 2023 00:20:41 +0900 Subject: [PATCH 23/43] Adjust colors --- .../SuggestView/FlickSuggestView.swift | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/AzooKeyCore/Sources/KeyboardViews/View/FlickKeyboard/SuggestView/FlickSuggestView.swift b/AzooKeyCore/Sources/KeyboardViews/View/FlickKeyboard/SuggestView/FlickSuggestView.swift index d06963fe..ad4022fe 100644 --- a/AzooKeyCore/Sources/KeyboardViews/View/FlickKeyboard/SuggestView/FlickSuggestView.swift +++ b/AzooKeyCore/Sources/KeyboardViews/View/FlickKeyboard/SuggestView/FlickSuggestView.swift @@ -14,6 +14,7 @@ import SwiftUI struct FlickSuggestView: View { @EnvironmentObject private var variableStates: VariableStates @Environment(Extension.Theme.self) private var theme + @Environment(\.colorScheme) private var colorScheme private let model: any FlickKeyModelProtocol private let suggestType: FlickSuggestType private let tabDesign: TabDependentDesign @@ -29,13 +30,19 @@ struct FlickSuggestView: Vi private func getSuggestView(for model: FlickedKeyModel, direction: FlickDirection, isHidden: Bool, isPointed: Bool = false) -> some View { // ポインテッド時の色を定義 var pointedColor: Color { - theme != Extension.ThemeExtension.default(layout: .flick) ? .white : .white + theme != Extension.ThemeExtension.default(layout: .flick) ? .white : .systemGray4 } // ポインテッドでない時の色を定義 var unpointedColor: Color { theme != Extension.ThemeExtension.default(layout: .flick) ? .white : .systemGray5 } - + var shadowColor: Color { + if colorScheme == .dark || theme != Extension.ThemeExtension.default(layout: .flick) { + .clear + } else { + .gray + } + } // 現在の状態に基づいて色を選択 let color = isPointed ? pointedColor : unpointedColor let shape: any Shape @@ -73,7 +80,7 @@ struct FlickSuggestView: Vi AnyView(shape .strokeAndFill(fillContent: color, strokeContent: theme.borderColor.color, lineWidth: theme.borderWidth)) .frame(width: size.width * sizeTimes[0], height: size.height * sizeTimes[1]) - .shadow(color: Color.gray, radius: 10, x: 5, y: 5) + .shadow(color: shadowColor, radius: 10, x: 5, y: 5) .overlay { KeyLabel(model.labelType, width: size.width, textColor: theme.suggestLabelTextColor?.color) .padding(EdgeInsets( From b8c5c944c69372a8bd82a4bba0f3ebcaad03326f Mon Sep 17 00:00:00 2001 From: ensan-hcl Date: Fri, 20 Oct 2023 00:28:21 +0900 Subject: [PATCH 24/43] Adjust colors --- .../View/FlickKeyboard/SuggestView/FlickSuggestView.swift | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/AzooKeyCore/Sources/KeyboardViews/View/FlickKeyboard/SuggestView/FlickSuggestView.swift b/AzooKeyCore/Sources/KeyboardViews/View/FlickKeyboard/SuggestView/FlickSuggestView.swift index ad4022fe..32321d69 100644 --- a/AzooKeyCore/Sources/KeyboardViews/View/FlickKeyboard/SuggestView/FlickSuggestView.swift +++ b/AzooKeyCore/Sources/KeyboardViews/View/FlickKeyboard/SuggestView/FlickSuggestView.swift @@ -30,7 +30,11 @@ struct FlickSuggestView: Vi private func getSuggestView(for model: FlickedKeyModel, direction: FlickDirection, isHidden: Bool, isPointed: Bool = false) -> some View { // ポインテッド時の色を定義 var pointedColor: Color { - theme != Extension.ThemeExtension.default(layout: .flick) ? .white : .systemGray4 + if colorScheme == .light || theme != Extension.ThemeExtension.default(layout: .flick) { + .white + } else { + .systemGray4 + } } // ポインテッドでない時の色を定義 var unpointedColor: Color { From 20c3093dfd3c71a1d6c902526a1e457ff3af872f Mon Sep 17 00:00:00 2001 From: ensan-hcl Date: Fri, 20 Oct 2023 10:30:08 +0900 Subject: [PATCH 25/43] adjust suggest positioning --- .../SuggestView/FlickSuggestView.swift | 36 +++++++++---------- 1 file changed, 16 insertions(+), 20 deletions(-) diff --git a/AzooKeyCore/Sources/KeyboardViews/View/FlickKeyboard/SuggestView/FlickSuggestView.swift b/AzooKeyCore/Sources/KeyboardViews/View/FlickKeyboard/SuggestView/FlickSuggestView.swift index 32321d69..9efd8b09 100644 --- a/AzooKeyCore/Sources/KeyboardViews/View/FlickKeyboard/SuggestView/FlickSuggestView.swift +++ b/AzooKeyCore/Sources/KeyboardViews/View/FlickKeyboard/SuggestView/FlickSuggestView.swift @@ -51,58 +51,45 @@ struct FlickSuggestView: Vi let color = isPointed ? pointedColor : unpointedColor let shape: any Shape let paddings: [CGFloat] - let spacers: [CGFloat] let sizeTimes: [CGFloat] switch direction { case .top: shape = RoundedPentagonTop() - paddings = [0, 0, 0.2, 0] - spacers = [0, 0, 0, 0.25] + paddings = [0, 0, 0.3, 0] sizeTimes = [1.2, 1.5] case .left: shape = RoundedPentagonLeft() paddings = [0, 0, 0, 0.3] - spacers = [0, 0, 0.1, 0] sizeTimes = [1.5, 1.2] case .right: shape = RoundedPentagonRight() paddings = [0, 0.3, 0, 0] - spacers = [0, 0.1, 0, 0] sizeTimes = [1.5, 1.2] case .bottom: shape = RoundedPentagonBottom() - paddings = [0.2, 0, 0, 0] - spacers = [0.25, 0, 0, 0] + paddings = [0.3, 0, 0, 0] sizeTimes = [1.2, 1.5] } - return VStack { - Spacer().frame(height: size.height * spacers[0]) - HStack { - Spacer().frame(width: size.width * spacers[1]) - AnyView(shape + return AnyView(shape .strokeAndFill(fillContent: color, strokeContent: theme.borderColor.color, lineWidth: theme.borderWidth)) .frame(width: size.width * sizeTimes[0], height: size.height * sizeTimes[1]) - .shadow(color: shadowColor, radius: 10, x: 5, y: 5) + .shadow(color: shadowColor, radius: 10, y: 5) .overlay { KeyLabel(model.labelType, width: size.width, textColor: theme.suggestLabelTextColor?.color) .padding(EdgeInsets( - top: size.width * paddings[0], + top: size.height * paddings[0], leading: size.width * paddings[1], - bottom: size.width * paddings[2], + bottom: size.height * paddings[2], trailing: size.width * paddings[3] )) } .allowsHitTesting(false) .opacity(isHidden ? 0 : 1) - Spacer().frame(width: size.width * spacers[2]) - } - Spacer().frame(height: size.height * spacers[3]) - } } /// その方向にViewの表示が必要な場合はサジェストのViewを、不要な場合は透明なViewを返す。 - @ViewBuilder private func getSuggestViewIfNecessary(direction: FlickDirection) -> some View { + private func getSuggestViewIfNecessary(direction: FlickDirection) -> some View { switch suggestType { case .all: if let model = self.model.flickKeys(variableStates: variableStates)[direction] { @@ -122,8 +109,12 @@ struct FlickSuggestView: Vi var body: some View { VStack(spacing: tabDesign.verticalSpacing) { self.getSuggestViewIfNecessary(direction: .top) + .offset(y: size.height / 2) + .zIndex(1) HStack(spacing: tabDesign.horizontalSpacing) { self.getSuggestViewIfNecessary(direction: .left) + .offset(x: size.width / 2) + .zIndex(1) RoundedRectangle(cornerRadius: 5.0) .strokeAndFill( fillContent: theme.specialKeyFillColor.color, @@ -131,9 +122,14 @@ struct FlickSuggestView: Vi lineWidth: theme.borderWidth ) .frame(width: size.width, height: size.height) + .zIndex(0) self.getSuggestViewIfNecessary(direction: .right) + .offset(x: -size.width / 2) + .zIndex(1) } self.getSuggestViewIfNecessary(direction: .bottom) + .offset(y: -size.height / 2) + .zIndex(1) } .frame(width: size.width, height: size.height) .allowsHitTesting(false) From 5c1543bcba8f33c1ac9742790a984c1e1f23df8f Mon Sep 17 00:00:00 2001 From: ensan-hcl Date: Fri, 20 Oct 2023 23:52:17 +0900 Subject: [PATCH 26/43] Complete better suggest implementation --- .../Sources/KeyboardViews/Design.swift | 3 + .../View/Components/KeyLabel.swift | 13 +- .../View/CustomKeybaord/CustomKeyboard.swift | 13 +- .../SuggestView/FlickSuggestView.swift | 156 +++++++++++++----- 4 files changed, 144 insertions(+), 41 deletions(-) diff --git a/AzooKeyCore/Sources/KeyboardViews/Design.swift b/AzooKeyCore/Sources/KeyboardViews/Design.swift index eddb7661..d99844ad 100644 --- a/AzooKeyCore/Sources/KeyboardViews/Design.swift +++ b/AzooKeyCore/Sources/KeyboardViews/Design.swift @@ -265,6 +265,7 @@ public enum Design { enum LabelFontSizeStrategy { case max + case xlarge case large case medium case small @@ -272,6 +273,8 @@ public enum Design { var scale: CGFloat { switch self { + case .xlarge: + return 1.2 case .large, .max: return 1 case .medium: diff --git a/AzooKeyCore/Sources/KeyboardViews/View/Components/KeyLabel.swift b/AzooKeyCore/Sources/KeyboardViews/View/Components/KeyLabel.swift index 156b5c32..0e3ac007 100644 --- a/AzooKeyCore/Sources/KeyboardViews/View/Components/KeyLabel.swift +++ b/AzooKeyCore/Sources/KeyboardViews/View/Components/KeyLabel.swift @@ -22,8 +22,8 @@ public enum KeyLabelType { public struct KeyLabel: View { private let labelType: KeyLabelType private let width: CGFloat - private let textColor: Color? - private let textSize: Design.Fonts.LabelFontSizeStrategy + private var textColor: Color? + private var textSize: Design.Fonts.LabelFontSizeStrategy @Environment(Extension.Theme.self) private var theme @Environment(\.userActionManager) private var action @EnvironmentObject private var variableStates: VariableStates @@ -99,4 +99,13 @@ public struct KeyLabel: Vie }.allowsHitTesting(false) } } + + consuming func textColor(_ color: Color?) -> Self { + self.textColor = color + return self + } + consuming func textSize(_ textSize: Design.Fonts.LabelFontSizeStrategy) -> Self { + self.textSize = textSize + return self + } } diff --git a/AzooKeyCore/Sources/KeyboardViews/View/CustomKeybaord/CustomKeyboard.swift b/AzooKeyCore/Sources/KeyboardViews/View/CustomKeybaord/CustomKeyboard.swift index 3be6497f..cc73e68f 100644 --- a/AzooKeyCore/Sources/KeyboardViews/View/CustomKeybaord/CustomKeyboard.swift +++ b/AzooKeyCore/Sources/KeyboardViews/View/CustomKeybaord/CustomKeyboard.swift @@ -359,22 +359,31 @@ public struct CustardFlickKeysView(model: data.model, tabDesign: tabDesign, size: info.size, suggestType: suggestType) .zIndex(2) } } .position(x: info.position.x, y: info.position.y) + .blur(radius: needBlur ? 0.75 : 0) } } .zIndex(columnSuggestStates.isEmpty ? 0 : 1) + .blur(radius: needColumnWideBlur ? 0.75 : 0) } .frame(width: tabDesign.keysWidth, height: tabDesign.keysHeight) } diff --git a/AzooKeyCore/Sources/KeyboardViews/View/FlickKeyboard/SuggestView/FlickSuggestView.swift b/AzooKeyCore/Sources/KeyboardViews/View/FlickKeyboard/SuggestView/FlickSuggestView.swift index 9efd8b09..45196e63 100644 --- a/AzooKeyCore/Sources/KeyboardViews/View/FlickKeyboard/SuggestView/FlickSuggestView.swift +++ b/AzooKeyCore/Sources/KeyboardViews/View/FlickKeyboard/SuggestView/FlickSuggestView.swift @@ -26,8 +26,16 @@ struct FlickSuggestView: Vi self.size = size self.suggestType = suggestType } - - private func getSuggestView(for model: FlickedKeyModel, direction: FlickDirection, isHidden: Bool, isPointed: Bool = false) -> some View { + + @ViewBuilder + private func keyLabel(for direction: FlickDirection, textColor: Color? = nil, textSize: Design.Fonts.LabelFontSizeStrategy = .xlarge) -> some View { + if let model = self.model.flickKeys(variableStates: variableStates)[direction] { + KeyLabel(model.labelType, width: size.width, textSize: textSize, textColor: textColor) + } else { + EmptyView() + } + } + private func getSuggestView(direction: FlickDirection, isHidden: Bool, isPointed: Bool) -> some View { // ポインテッド時の色を定義 var pointedColor: Color { if colorScheme == .light || theme != Extension.ThemeExtension.default(layout: .flick) { @@ -77,7 +85,7 @@ struct FlickSuggestView: Vi .frame(width: size.width * sizeTimes[0], height: size.height * sizeTimes[1]) .shadow(color: shadowColor, radius: 10, y: 5) .overlay { - KeyLabel(model.labelType, width: size.width, textColor: theme.suggestLabelTextColor?.color) + self.keyLabel(for: direction, textColor: theme.suggestLabelTextColor?.color) .padding(EdgeInsets( top: size.height * paddings[0], leading: size.width * paddings[1], @@ -89,50 +97,124 @@ struct FlickSuggestView: Vi .opacity(isHidden ? 0 : 1) } /// その方向にViewの表示が必要な場合はサジェストのViewを、不要な場合は透明なViewを返す。 - private func getSuggestViewIfNecessary(direction: FlickDirection) -> some View { - switch suggestType { - case .all: - if let model = self.model.flickKeys(variableStates: variableStates)[direction] { - getSuggestView(for: model, direction: direction, isHidden: false) - } else { - getSuggestView(for: .empty, direction: direction, isHidden: true) - } - case .flick(let targetDirection): - if targetDirection == direction, let model = self.model.flickKeys(variableStates: variableStates)[direction] { - getSuggestView(for: model, direction: direction, isHidden: false, isPointed: true) + @ViewBuilder + private func getPointedSuggestViewIfNecessary(direction: FlickDirection, targetDirection: FlickDirection) -> some View { + if targetDirection == direction { + getSuggestView(direction: direction, isHidden: false, isPointed: true) + } else { + getSuggestView(direction: direction, isHidden: true, isPointed: false) + } + } + + @ViewBuilder + private func roundedRectangleForAllSuggest(cornerRadius: CGFloat, direction: FlickDirection, sizeDiff: CGFloat = 2) -> some View { + var color: Color { + if colorScheme == .light || theme != Extension.ThemeExtension.default(layout: .flick) { + .white } else { - getSuggestView(for: .empty, direction: direction, isHidden: true) + .systemGray4 } } + let widthDiff: CGFloat = switch direction { + case .top, .bottom: tabDesign.horizontalSpacing + case .left, .right: tabDesign.horizontalSpacing / 2 + cornerRadius + sizeDiff + } + let heightDiff: CGFloat = switch direction { + case .top, .bottom: tabDesign.verticalSpacing / 2 + cornerRadius + sizeDiff + case .left, .right: tabDesign.verticalSpacing + } + let isHidden = !self.model.isFlickAble(to: direction, variableStates: variableStates) + RoundedRectangle(cornerRadius: cornerRadius) + .strokeAndFill(fillContent: color, strokeContent: theme.borderColor.color, lineWidth: theme.borderWidth) + .frame(width: size.width + widthDiff, height: size.height + heightDiff) + .overlay { + let offsetX: CGFloat = switch direction { + case .bottom, .top: 0 + case .left: -cornerRadius + sizeDiff/2 + case .right: cornerRadius - sizeDiff/2 + } + let offsetY: CGFloat = switch direction { + case .left, .right: 0 + case .top: -cornerRadius + sizeDiff/2 + case .bottom: cornerRadius - sizeDiff/2 + } + self.keyLabel(for: direction, textColor: theme.suggestLabelTextColor?.color) + .offset(x: offsetX, y: offsetY) + } + .opacity(isHidden ? 0 : 1) } var body: some View { - VStack(spacing: tabDesign.verticalSpacing) { - self.getSuggestViewIfNecessary(direction: .top) - .offset(y: size.height / 2) - .zIndex(1) - HStack(spacing: tabDesign.horizontalSpacing) { - self.getSuggestViewIfNecessary(direction: .left) - .offset(x: size.width / 2) + switch self.suggestType { + case .all: + let cornerRadius = 5.0 + VStack(spacing: 0) { + roundedRectangleForAllSuggest(cornerRadius: cornerRadius, direction: .top) + .offset(y: cornerRadius) .zIndex(1) - RoundedRectangle(cornerRadius: 5.0) - .strokeAndFill( - fillContent: theme.specialKeyFillColor.color, - strokeContent: theme.borderColor.color, - lineWidth: theme.borderWidth - ) - .frame(width: size.width, height: size.height) - .zIndex(0) - self.getSuggestViewIfNecessary(direction: .right) - .offset(x: -size.width / 2) + HStack(spacing: 0) { + roundedRectangleForAllSuggest(cornerRadius: cornerRadius, direction: .left) + .offset(x: cornerRadius) + .zIndex(1) + Rectangle() + .strokeAndFill( + fillContent: .blue, + strokeContent: .gray, + lineWidth: 0.5 + ) + .frame( + width: size.width + tabDesign.horizontalSpacing, + height: size.height + tabDesign.verticalSpacing + ) + .zIndex(2) + .overlay { + (self.model.label(width: size.width, states: variableStates) as KeyLabel) + .textColor(.white) + .textSize(.xlarge) + } + roundedRectangleForAllSuggest(cornerRadius: cornerRadius, direction: .right) + .offset(x: -cornerRadius) + .zIndex(1) + } + .zIndex(2) + .frame(width: size.width + tabDesign.horizontalSpacing, height: size.height + tabDesign.verticalSpacing) + roundedRectangleForAllSuggest(cornerRadius: cornerRadius, direction: .bottom) + .offset(y: -cornerRadius) + .zIndex(1) + } + .compositingGroup() + .shadow(color: .gray, radius: 3) + .frame(width: size.width, height: size.height) + .allowsHitTesting(false) + case .flick(let targetDirection): + VStack(spacing: tabDesign.verticalSpacing) { + self.getPointedSuggestViewIfNecessary(direction: .top, targetDirection: targetDirection) + .offset(y: size.height / 2) + .zIndex(1) + HStack(spacing: tabDesign.horizontalSpacing) { + self.getPointedSuggestViewIfNecessary(direction: .left, targetDirection: targetDirection) + .offset(x: size.width / 2) + .zIndex(1) + RoundedRectangle(cornerRadius: 5.0) + .strokeAndFill( + fillContent: theme.specialKeyFillColor.color, + strokeContent: theme.borderColor.color, + lineWidth: theme.borderWidth + ) + .frame(width: size.width, height: size.height) + .zIndex(0) + self.getPointedSuggestViewIfNecessary(direction: .right, targetDirection: targetDirection) + .offset(x: -size.width / 2) + .zIndex(1) + } + .frame(width: size.width, height: size.height) + self.getPointedSuggestViewIfNecessary(direction: .bottom, targetDirection: targetDirection) + .offset(y: -size.height / 2) .zIndex(1) } - self.getSuggestViewIfNecessary(direction: .bottom) - .offset(y: -size.height / 2) - .zIndex(1) + .frame(width: size.width, height: size.height) + .allowsHitTesting(false) } - .frame(width: size.width, height: size.height) - .allowsHitTesting(false) } } From c4e30f5ba73322eade88c636ced8c81742addb17 Mon Sep 17 00:00:00 2001 From: ensan-hcl Date: Fri, 20 Oct 2023 23:59:27 +0900 Subject: [PATCH 27/43] format --- .../SuggestView/FlickSuggestView.swift | 77 +++++++++---------- 1 file changed, 38 insertions(+), 39 deletions(-) diff --git a/AzooKeyCore/Sources/KeyboardViews/View/FlickKeyboard/SuggestView/FlickSuggestView.swift b/AzooKeyCore/Sources/KeyboardViews/View/FlickKeyboard/SuggestView/FlickSuggestView.swift index 45196e63..d4646ba7 100644 --- a/AzooKeyCore/Sources/KeyboardViews/View/FlickKeyboard/SuggestView/FlickSuggestView.swift +++ b/AzooKeyCore/Sources/KeyboardViews/View/FlickKeyboard/SuggestView/FlickSuggestView.swift @@ -19,7 +19,7 @@ struct FlickSuggestView: Vi private let suggestType: FlickSuggestType private let tabDesign: TabDependentDesign private let size: CGSize - + init(model: any FlickKeyModelProtocol, tabDesign: TabDependentDesign, size: CGSize, suggestType: FlickSuggestType) { self.model = model self.tabDesign = tabDesign @@ -60,7 +60,7 @@ struct FlickSuggestView: Vi let shape: any Shape let paddings: [CGFloat] let sizeTimes: [CGFloat] - + switch direction { case .top: shape = RoundedPentagonTop() @@ -79,22 +79,21 @@ struct FlickSuggestView: Vi paddings = [0.3, 0, 0, 0] sizeTimes = [1.2, 1.5] } - - return AnyView(shape - .strokeAndFill(fillContent: color, strokeContent: theme.borderColor.color, lineWidth: theme.borderWidth)) - .frame(width: size.width * sizeTimes[0], height: size.height * sizeTimes[1]) - .shadow(color: shadowColor, radius: 10, y: 5) - .overlay { - self.keyLabel(for: direction, textColor: theme.suggestLabelTextColor?.color) - .padding(EdgeInsets( - top: size.height * paddings[0], - leading: size.width * paddings[1], - bottom: size.height * paddings[2], - trailing: size.width * paddings[3] - )) - } - .allowsHitTesting(false) - .opacity(isHidden ? 0 : 1) + + return AnyView(shape.strokeAndFill(fillContent: color, strokeContent: theme.borderColor.color, lineWidth: theme.borderWidth)) + .frame(width: size.width * sizeTimes[0], height: size.height * sizeTimes[1]) + .shadow(color: shadowColor, radius: 10, y: 5) + .overlay { + self.keyLabel(for: direction, textColor: theme.suggestLabelTextColor?.color) + .padding(EdgeInsets( + top: size.height * paddings[0], + leading: size.width * paddings[1], + bottom: size.height * paddings[2], + trailing: size.width * paddings[3] + )) + } + .allowsHitTesting(false) + .opacity(isHidden ? 0 : 1) } /// その方向にViewの表示が必要な場合はサジェストのViewを、不要な場合は透明なViewを返す。 @ViewBuilder @@ -130,20 +129,20 @@ struct FlickSuggestView: Vi .overlay { let offsetX: CGFloat = switch direction { case .bottom, .top: 0 - case .left: -cornerRadius + sizeDiff/2 - case .right: cornerRadius - sizeDiff/2 + case .left: -cornerRadius + sizeDiff / 2 + case .right: cornerRadius - sizeDiff / 2 } let offsetY: CGFloat = switch direction { case .left, .right: 0 - case .top: -cornerRadius + sizeDiff/2 - case .bottom: cornerRadius - sizeDiff/2 + case .top: -cornerRadius + sizeDiff / 2 + case .bottom: cornerRadius - sizeDiff / 2 } self.keyLabel(for: direction, textColor: theme.suggestLabelTextColor?.color) .offset(x: offsetX, y: offsetY) } .opacity(isHidden ? 0 : 1) } - + var body: some View { switch self.suggestType { case .all: @@ -216,47 +215,47 @@ struct FlickSuggestView: Vi .allowsHitTesting(false) } } - + } - + private extension Path { mutating func addRoundedPentagon(using points: [CGPoint], cornerRadius: CGFloat = 5) { guard points.count == 5 else { return } - + for i in 0 ..< 5 { let currentPoint = points[i] let nextPoint = points[(i + 1) % 5] let prevPoint = i == 0 ? points.last! : points[i - 1] - + let directionFromPrev = CGVector(dx: currentPoint.x - prevPoint.x, dy: currentPoint.y - prevPoint.y).normalized let directionToNext = CGVector(dx: nextPoint.x - currentPoint.x, dy: nextPoint.y - currentPoint.y).normalized - + let offsetFromCurrent1 = CGVector(dx: directionFromPrev.dx * cornerRadius, dy: directionFromPrev.dy * cornerRadius) let offsetFromCurrent2 = CGVector(dx: directionToNext.dx * cornerRadius, dy: directionToNext.dy * cornerRadius) - + if i == 0 { move(to: CGPoint(x: currentPoint.x - offsetFromCurrent1.dx, y: currentPoint.y - offsetFromCurrent1.dy)) } else { addLine(to: CGPoint(x: currentPoint.x - offsetFromCurrent1.dx, y: currentPoint.y - offsetFromCurrent1.dy)) } - + addQuadCurve(to: CGPoint(x: currentPoint.x + offsetFromCurrent2.dx, y: currentPoint.y + offsetFromCurrent2.dy), control: currentPoint) } - + closeSubpath() } } - + private extension CGVector { var length: CGFloat { - return sqrt(dx * dx + dy * dy) + sqrt(dx * dx + dy * dy) } - + var normalized: CGVector { - return CGVector(dx: dx / length, dy: dy / length) + CGVector(dx: dx / length, dy: dy / length) } } - + private struct RoundedPentagonBottom: Shape { func path(in rect: CGRect) -> Path { var path = Path() @@ -271,7 +270,7 @@ private struct RoundedPentagonBottom: Shape { return path } } - + private struct RoundedPentagonLeft: Shape { func path(in rect: CGRect) -> Path { var path = Path() @@ -286,7 +285,7 @@ private struct RoundedPentagonLeft: Shape { return path } } - + private struct RoundedPentagonRight: Shape { func path(in rect: CGRect) -> Path { var path = Path() @@ -301,7 +300,7 @@ private struct RoundedPentagonRight: Shape { return path } } - + private struct RoundedPentagonTop: Shape { func path(in rect: CGRect) -> Path { var path = Path() From 6c4585af6b841e5d6c2cede4eaf6c240b685e79d Mon Sep 17 00:00:00 2001 From: ensan-hcl Date: Sat, 21 Oct 2023 00:02:21 +0900 Subject: [PATCH 28/43] Make blur available only in default keyboard, due to performance issue --- .../KeyboardViews/View/CustomKeybaord/CustomKeyboard.swift | 7 ++++--- .../View/FlickKeyboard/FlickKeyboardView.swift | 2 +- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/AzooKeyCore/Sources/KeyboardViews/View/CustomKeybaord/CustomKeyboard.swift b/AzooKeyCore/Sources/KeyboardViews/View/CustomKeybaord/CustomKeyboard.swift index cc73e68f..c858f9c1 100644 --- a/AzooKeyCore/Sources/KeyboardViews/View/CustomKeybaord/CustomKeyboard.swift +++ b/AzooKeyCore/Sources/KeyboardViews/View/CustomKeybaord/CustomKeyboard.swift @@ -337,10 +337,11 @@ struct CustomKeyboardView: public struct CustardFlickKeysView: View { @State private var suggestState = FlickSuggestState() - public init(models: [KeyPosition: (model: any FlickKeyModelProtocol, width: Int, height: Int)], tabDesign: TabDependentDesign, layout: CustardInterfaceLayoutGridValue, @ViewBuilder generator: @escaping (FlickKeyView, Int, Int) -> (Content)) { + public init(models: [KeyPosition: (model: any FlickKeyModelProtocol, width: Int, height: Int)], tabDesign: TabDependentDesign, layout: CustardInterfaceLayoutGridValue, blur: Bool = false, @ViewBuilder generator: @escaping (FlickKeyView, Int, Int) -> (Content)) { self.models = models self.tabDesign = tabDesign self.layout = layout + self.blur = blur self.contentGenerator = generator } @@ -348,6 +349,7 @@ public struct CustardFlickKeysView (position: CGPoint, size: CGSize) { let width = tabDesign.keyViewWidth(widthCount: width) @@ -360,8 +362,7 @@ public struct CustardFlickKeysView: V var body: some View { let layout = CustardInterfaceLayoutGridValue(rowCount: Int(tabDesign.horizontalKeyCount), columnCount: Int(tabDesign.verticalKeyCount)) - CustardFlickKeysView(models: models, tabDesign: tabDesign, layout: layout) {(view: FlickKeyView, _, _) in + CustardFlickKeysView(models: models, tabDesign: tabDesign, layout: layout, blur: true) {(view: FlickKeyView, _, _) in view } } From 28aa21b485f78a7844129292f91b441e89a41acd Mon Sep 17 00:00:00 2001 From: ensan-hcl Date: Sun, 22 Oct 2023 00:25:13 +0900 Subject: [PATCH 29/43] add dismiss delay to flick suggests --- .../View/FlickKeyboard/KeyView/FlickKeyView.swift | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/AzooKeyCore/Sources/KeyboardViews/View/FlickKeyboard/KeyView/FlickKeyView.swift b/AzooKeyCore/Sources/KeyboardViews/View/FlickKeyboard/KeyView/FlickKeyView.swift index 2920f698..80ccc77b 100644 --- a/AzooKeyCore/Sources/KeyboardViews/View/FlickKeyboard/KeyView/FlickKeyView.swift +++ b/AzooKeyCore/Sources/KeyboardViews/View/FlickKeyboard/KeyView/FlickKeyView.swift @@ -32,6 +32,7 @@ public struct FlickKeyView: @State private var pressState: KeyPressState = .inactive @Binding private var suggestState: FlickSuggestState + @State private var suggestDismissTask: Task? // TODO: 消せるはず @State private var startLocation: CGPoint? @@ -97,6 +98,8 @@ public struct FlickKeyView: self.setSuggestState(nil) // 一つの方向でサジェストされた状態を登録する。 pressState = .oneDirectionSuggested(d, Date()) + // もしサジェストを非表示にするタスクが走っていたら、キャンセルする + self.suggestDismissTask?.cancel() // 長押しされなかったと判断して終了する。 self.action.registerLongPressActionEnd(self.model.longPressActions(variableStates: variableStates)) // 長フリックを予約する @@ -164,8 +167,13 @@ public struct FlickKeyView: // タップの終了時 .onEnded {_ in // サジェストを解除する - self.setSuggestState(nil) - + // 少しdelayを入れることで表示がはっきりして、「フリックした感」が強まる + self.suggestDismissTask = Task { + // 0.1秒だともたつき感、0.05秒だと短すぎ、という感じ + try await Task.sleep(nanoseconds: 0_070_000_000) + try Task.checkCancellation() + self.setSuggestState(nil) + } // 押しはじめて、そのあと動きがなかった場合ここに来る。 if case let .started(date) = pressState { // もし0.4秒以上経っていたら From 16b2b06f159c7808fb246b7040d9eb3296c6d75b Mon Sep 17 00:00:00 2001 From: ensan-hcl Date: Sun, 22 Oct 2023 16:34:36 +0900 Subject: [PATCH 30/43] Add shift key setting --- .../AzooKeyUtils/AzooKeyKeyboardViewExtension.swift | 2 +- .../KeyboardSetting/BoolKeyboardSetting.swift | 11 +++++++++++ MainApp/Setting/SettingTab.swift | 10 ++++++++++ 3 files changed, 22 insertions(+), 1 deletion(-) diff --git a/AzooKeyCore/Sources/AzooKeyUtils/AzooKeyKeyboardViewExtension.swift b/AzooKeyCore/Sources/AzooKeyUtils/AzooKeyKeyboardViewExtension.swift index db80f08b..608f5d30 100644 --- a/AzooKeyCore/Sources/AzooKeyUtils/AzooKeyKeyboardViewExtension.swift +++ b/AzooKeyCore/Sources/AzooKeyUtils/AzooKeyKeyboardViewExtension.swift @@ -95,7 +95,7 @@ public enum AzooKeyKeyboardViewExtension: ApplicationSpecificKeyboardViewExtensi } public static var useShiftKey: Bool { - false + UseShiftKey.value } public static var canResetLearningForCandidate: Bool { diff --git a/AzooKeyCore/Sources/AzooKeyUtils/KeyboardSetting/BoolKeyboardSetting.swift b/AzooKeyCore/Sources/AzooKeyUtils/KeyboardSetting/BoolKeyboardSetting.swift index e9238240..83ea01d2 100644 --- a/AzooKeyCore/Sources/AzooKeyUtils/KeyboardSetting/BoolKeyboardSetting.swift +++ b/AzooKeyCore/Sources/AzooKeyUtils/KeyboardSetting/BoolKeyboardSetting.swift @@ -179,6 +179,17 @@ public extension KeyboardSettingKey where Self == UseSliderStyleCursorBar { static var useSliderStyleCursorBar: Self { .init() } } +public struct UseShiftKey: BoolKeyboardSettingKey { + public static let title: LocalizedStringKey = "シフトキーを使う" + public static let explanation: LocalizedStringKey = "QwertyキーボードでAaキーの代わりにシフトキーを利用します。" + public static let defaultValue = false + public static let key: String = "use_shift_key" +} + +public extension KeyboardSettingKey where Self == UseShiftKey { + static var useShiftKey: Self { .init() } +} + public struct HideResetButtonInOneHandedMode: BoolKeyboardSettingKey { public static let title: LocalizedStringKey = "片手モードで解除ボタンを表示しない" public static let explanation: LocalizedStringKey = "片手モードの際に表示される解除ボタンを非表示にします。片手モードの調整はタブバーのボタンから行えます。" diff --git a/MainApp/Setting/SettingTab.swift b/MainApp/Setting/SettingTab.swift index 00bf26bd..2c3520aa 100644 --- a/MainApp/Setting/SettingTab.swift +++ b/MainApp/Setting/SettingTab.swift @@ -23,6 +23,13 @@ struct SettingTabView: View { return false } + private func canQwertyLayout(_ layout: LanguageLayout) -> Bool { + if layout == .qwerty { + return true + } + return false + } + var body: some View { NavigationView { Form { @@ -73,6 +80,9 @@ struct SettingTabView: View { if self.canFlickLayout(appStates.japaneseLayout) { FlickSensitivitySettingView(.flickSensitivity) } + if self.canQwertyLayout(appStates.englishLayout) { + BoolSettingView(.useShiftKey) + } } } Group { From c022f705fd3211fb264ae9d3e14bba9fcb775c02 Mon Sep 17 00:00:00 2001 From: ensan-hcl Date: Sun, 22 Oct 2023 16:35:07 +0900 Subject: [PATCH 31/43] update info --- MainApp/UpdateInformationView.swift | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/MainApp/UpdateInformationView.swift b/MainApp/UpdateInformationView.swift index d2437a2a..6a7ce511 100644 --- a/MainApp/UpdateInformationView.swift +++ b/MainApp/UpdateInformationView.swift @@ -24,7 +24,7 @@ struct UpdateInformationView: View { } ParagraphView("予測変換を大幅に強化しました。") { "確定したあとに続けて打つ文字を予測するようになりました" - "より妥当な候補が表示されるようになりました" + "より妥当な予測候補が表示されるようになりました" } ParagraphView("機能を改善しました。") { "再変換を大幅に強化しました。" @@ -33,6 +33,11 @@ struct UpdateInformationView: View { "カーソルを動かした際、カーソルバーを表示するようにしました" "カスタムキーで「次候補」と「A/a」の特殊キーを選べるようになりました" } + ParagraphView("デザインを改善しました") { + "サジェストをよりはっきりと表示するようにしました" + "カーソルバーのデザインを改善しました" + "iPadでのデザインを改善しました" + } ParagraphView("複数の不具合を修正しました。") ParagraphView("その他辞書の改善を行いました。") } From b12a953eb14b00b18b2feca39322c16e704c840f Mon Sep 17 00:00:00 2001 From: ensan-hcl Date: Sun, 22 Oct 2023 23:45:03 +0900 Subject: [PATCH 32/43] Update theme tab design --- MainApp/Theme/ThemeTab.swift | 128 ++++++++++++++++---------------- Resources/Localizable.xcstrings | 30 ++++++++ 2 files changed, 96 insertions(+), 62 deletions(-) diff --git a/MainApp/Theme/ThemeTab.swift b/MainApp/Theme/ThemeTab.swift index 1db67ef7..3355222c 100644 --- a/MainApp/Theme/ThemeTab.swift +++ b/MainApp/Theme/ThemeTab.swift @@ -31,9 +31,8 @@ struct ThemeTabView: View { } @MainActor - private func circle(geometry: GeometryProxy, systemName: String, color: Color) -> some View { - let width = min(min(geometry.size.width / 1.5, 180), geometry.size.height / 2.5) // 高さに2つ入るサイズを超えないように設定 - return Circle() + private func circle(width: CGFloat, systemName: String, color: Color) -> some View { + Circle() .fill(color) .frame(width: width, height: width) .overlay( @@ -43,45 +42,6 @@ struct ThemeTabView: View { ) } - @MainActor - private func selectButton(_ index: Int) -> some View { - GeometryReader {geometry in - if manager.selectedIndex == manager.selectedIndexInDarkMode { - CenterAlignedView { - VStack { - Spacer() - circle(geometry: geometry, systemName: "checkmark", color: manager.selectedIndex == index ? Color.blue : Color.systemGray4) - .matchedGeometryEffect(id: "ThemeLightButton\(index)", in: namespace) - .matchedGeometryEffect(id: "ThemeDarkButton\(index)", in: namespace) - Spacer() - } - .onTapGesture { - manager.select(at: index) - } - } - } else { - CenterAlignedView { - VStack { - Spacer() - circle(geometry: geometry, systemName: "sun.max.fill", color: manager.selectedIndex == index ? Color.blue : Color.systemGray4) - .matchedGeometryEffect(id: "ThemeLightButton\(index)", in: namespace) - .onTapGesture { - manager.selectForLightMode(at: index) - } - Spacer(minLength: 10) - circle(geometry: geometry, systemName: "moon.fill", color: manager.selectedIndexInDarkMode == index ? Color.blue : Color.systemGray4) - .matchedGeometryEffect(id: "ThemeDarkButton\(index)", in: namespace) - .onTapGesture { - manager.selectForDarkMode(at: index) - } - Spacer() - } - } - } - } - .animation(.easeIn(duration: 0.2), value: manager.selectedIndex == manager.selectedIndexInDarkMode) - } - private var tab: Tab.ExistentialTab { switch appStates.japaneseLayout { case .flick: @@ -99,9 +59,62 @@ struct ThemeTabView: View { ForEach(manager.indices.reversed(), id: \.self) { index in if let theme = theme(at: index) { HStack { - KeyboardPreview(theme: theme, scale: 0.6, defaultTab: tab) - .disabled(true) - selectButton(index) + ZStack { + KeyboardPreview(theme: theme, scale: 0.6, defaultTab: tab) + .disabled(true) + .overlay { + if manager.selectedIndex == index || manager.selectedIndexInDarkMode == index { + Color.black.opacity(0.3) + } + } + .onTapGesture { + if manager.selectedIndex != index && manager.selectedIndexInDarkMode != index { + self.manager.select(at: index) + } + } + if manager.selectedIndex == manager.selectedIndexInDarkMode, + manager.selectedIndex == index { + circle(width: 80, systemName: "checkmark", color: .blue) + .matchedGeometryEffect(id: "selected_theme_checkmark", in: namespace) + } else if manager.selectedIndex == index { + circle(width: 80, systemName: "sun.max.fill", color: .blue) + .matchedGeometryEffect(id: "selected_theme_light", in: namespace) + } else if manager.selectedIndexInDarkMode == index { + circle(width: 80, systemName: "moon.fill", color: .blue) + .matchedGeometryEffect(id: "selected_theme_dark", in: namespace) + } + } + Spacer() + VStack { + if manager.selectedIndex == manager.selectedIndexInDarkMode { + if manager.selectedIndex != index { + Button("選択", systemImage: "checkmark") { + manager.select(at: index) + } + } + } else { + if manager.selectedIndex != index { + Button("ライトモード", systemImage: "sun.max.fill") { + manager.selectForLightMode(at: index) + } + } + if manager.selectedIndexInDarkMode != index { + Button("ダークモード", systemImage: "moon.fill") { + manager.selectForDarkMode(at: index) + } + } + } + if index != 0 { + Button("編集", systemImage: "slider.horizontal.3") { + editViewIndex = index + editViewEnabled = true + } + } + } + .labelStyle(.iconOnly) + .buttonStyle(LargeButtonStyle(backgroundColor: .systemGray5)) + Spacer() + // 編集用 if editViewIndex == index { NavigationLink(destination: ThemeEditView(index: editViewIndex, manager: $manager), isActive: $editViewEnabled) { EmptyView() @@ -110,36 +123,27 @@ struct ThemeTabView: View { } .contextMenu { if self.manager.selectedIndex == self.manager.selectedIndexInDarkMode { - Button { + Button("ライトモードで使用", systemImage: "sun.max.fill") { manager.selectForLightMode(at: index) - } label: { - Image(systemName: "sun.max.fill") - Text("ライトモードで使用") } - Button { + Button("ダークモードで使用", systemImage: "moon.fill") { manager.selectForDarkMode(at: index) - } label: { - Image(systemName: "moon.fill") - Text("ダークモードで使用") } } - Button { + Button("編集する", systemImage: "slider.horizontal.3") { editViewIndex = index editViewEnabled = true - } label: { - Image(systemName: "pencil") - Text("編集する") - }.disabled(index == 0) - Button(role: .destructive) { + } + .disabled(index == 0) + Button("削除する", systemImage: "trash", role: .destructive) { manager.remove(index: index) - } label: { - Label("削除する", systemImage: "trash") - .foregroundStyle(.red) } .disabled(index == 0) } } } + .animation(.easeIn(duration: 0.15), value: manager.selectedIndex) + .animation(.easeIn(duration: 0.15), value: manager.selectedIndexInDarkMode) } var body: some View { diff --git a/Resources/Localizable.xcstrings b/Resources/Localizable.xcstrings index 7bfb0cbd..268f425b 100644 --- a/Resources/Localizable.xcstrings +++ b/Resources/Localizable.xcstrings @@ -3582,6 +3582,16 @@ } } }, + "ダークモード" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Dark mode" + } + } + } + }, "ダークモードで使用" : { "localizations" : { "en" : { @@ -4836,6 +4846,16 @@ } } }, + "ライトモード" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Light mode" + } + } + } + }, "ライトモードで使用" : { "localizations" : { "en" : { @@ -9623,6 +9643,16 @@ } } }, + "選択" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Select" + } + } + } + }, "長押し" : { "extractionState" : "manual", "localizations" : { From 5566b2075596a8273e5aaefa632d20a2ccea5025 Mon Sep 17 00:00:00 2001 From: ensan-hcl Date: Mon, 23 Oct 2023 10:34:08 +0900 Subject: [PATCH 33/43] Remove dependency on keyboard layout in vertical spacing calculation --- .../Sources/KeyboardViews/Design.swift | 25 +++++++------------ .../View/CustomKeybaord/CustomKeyboard.swift | 6 ++--- .../FlickKeyboard/FlickKeyboardView.swift | 2 +- .../QwertyKeyboard/QwertyKeyboardView.swift | 2 +- .../SpecialTabs/ClipboardHistoryTab.swift | 4 +-- .../View/SpecialTabs/EmojiTab.swift | 2 +- .../Customize/EditingTenkeyCustardView.swift | 2 +- 7 files changed, 18 insertions(+), 25 deletions(-) diff --git a/AzooKeyCore/Sources/KeyboardViews/Design.swift b/AzooKeyCore/Sources/KeyboardViews/Design.swift index d99844ad..ee15c5f0 100644 --- a/AzooKeyCore/Sources/KeyboardViews/Design.swift +++ b/AzooKeyCore/Sources/KeyboardViews/Design.swift @@ -15,25 +15,22 @@ import SwiftUIUtils public struct TabDependentDesign { let horizontalKeyCount: CGFloat let verticalKeyCount: CGFloat - let layout: KeyboardLayout let orientation: KeyboardOrientation private var interfaceWidth: CGFloat private var interfaceHeight: CGFloat - public init(width: Int, height: Int, interfaceSize: CGSize, layout: KeyboardLayout, orientation: KeyboardOrientation) { + public init(width: Int, height: Int, interfaceSize: CGSize, orientation: KeyboardOrientation) { self.horizontalKeyCount = CGFloat(width) self.verticalKeyCount = CGFloat(height) - self.layout = layout self.orientation = orientation self.interfaceWidth = interfaceSize.width self.interfaceHeight = interfaceSize.height } - public init(width: CGFloat, height: CGFloat, interfaceSize: CGSize, layout: KeyboardLayout, orientation: KeyboardOrientation) { + public init(width: CGFloat, height: CGFloat, interfaceSize: CGSize, orientation: KeyboardOrientation) { self.horizontalKeyCount = width self.verticalKeyCount = height - self.layout = layout self.orientation = orientation self.interfaceWidth = interfaceSize.width self.interfaceHeight = interfaceSize.height @@ -42,10 +39,10 @@ public struct TabDependentDesign { /// screenWidthとhorizontalKeyCountに依存 var keyViewWidth: CGFloat { let coefficient: CGFloat - switch (layout, orientation) { - case (_, .vertical): + switch orientation { + case .vertical: coefficient = 5 / (5.1 + horizontalKeyCount / 10) - case (_, .horizontal): + case .horizontal: coefficient = 10 / (10.2 + horizontalKeyCount * 0.28) } return interfaceWidth / horizontalKeyCount * coefficient @@ -72,15 +69,11 @@ public struct TabDependentDesign { } var verticalSpacing: CGFloat { - switch (layout, orientation) { - case (.flick, .vertical): - return interfaceWidth * 3 / 140 - case (.flick, .horizontal): + switch orientation { + case .vertical: + return interfaceWidth / 50 + case .horizontal: return interfaceWidth / 107 - case (.qwerty, .vertical): - return interfaceWidth / 36.6 - case (.qwerty, .horizontal): - return interfaceWidth / 65 } } diff --git a/AzooKeyCore/Sources/KeyboardViews/View/CustomKeybaord/CustomKeyboard.swift b/AzooKeyCore/Sources/KeyboardViews/View/CustomKeybaord/CustomKeyboard.swift index c858f9c1..df65eead 100644 --- a/AzooKeyCore/Sources/KeyboardViews/View/CustomKeybaord/CustomKeyboard.swift +++ b/AzooKeyCore/Sources/KeyboardViews/View/CustomKeybaord/CustomKeyboard.swift @@ -49,13 +49,13 @@ fileprivate extension CustardInterface { func tabDesign(interfaceSize: CGSize, keyboardOrientation: KeyboardOrientation) -> TabDependentDesign { switch self.keyLayout { case let .gridFit(value): - return TabDependentDesign(width: value.rowCount, height: value.columnCount, interfaceSize: interfaceSize, layout: keyStyle.keyboardLayout, orientation: keyboardOrientation) + return TabDependentDesign(width: value.rowCount, height: value.columnCount, interfaceSize: interfaceSize, orientation: keyboardOrientation) case let .gridScroll(value): switch value.direction { case .vertical: - return TabDependentDesign(width: CGFloat(Int(value.rowCount)), height: CGFloat(value.columnCount), interfaceSize: interfaceSize, layout: .flick, orientation: keyboardOrientation) + return TabDependentDesign(width: CGFloat(Int(value.rowCount)), height: CGFloat(value.columnCount), interfaceSize: interfaceSize, orientation: keyboardOrientation) case .horizontal: - return TabDependentDesign(width: CGFloat(value.rowCount), height: CGFloat(Int(value.columnCount)), interfaceSize: interfaceSize, layout: .flick, orientation: keyboardOrientation) + return TabDependentDesign(width: CGFloat(value.rowCount), height: CGFloat(Int(value.columnCount)), interfaceSize: interfaceSize, orientation: keyboardOrientation) } } } diff --git a/AzooKeyCore/Sources/KeyboardViews/View/FlickKeyboard/FlickKeyboardView.swift b/AzooKeyCore/Sources/KeyboardViews/View/FlickKeyboard/FlickKeyboardView.swift index 05685bc9..049b76bb 100644 --- a/AzooKeyCore/Sources/KeyboardViews/View/FlickKeyboard/FlickKeyboardView.swift +++ b/AzooKeyCore/Sources/KeyboardViews/View/FlickKeyboard/FlickKeyboardView.swift @@ -16,7 +16,7 @@ struct FlickKeyboardView: V private let tabDesign: TabDependentDesign private let models: [KeyPosition: (model: any FlickKeyModelProtocol, width: Int, height: Int)] init(keyModels: [[any FlickKeyModelProtocol]], interfaceSize: CGSize, keyboardOrientation: KeyboardOrientation) { - self.tabDesign = TabDependentDesign(width: 5, height: 4, interfaceSize: interfaceSize, layout: .flick, orientation: keyboardOrientation) + self.tabDesign = TabDependentDesign(width: 5, height: 4, interfaceSize: interfaceSize, orientation: keyboardOrientation) var models: [KeyPosition: (model: any FlickKeyModelProtocol, width: Int, height: Int)] = [:] for h in keyModels.indices { diff --git a/AzooKeyCore/Sources/KeyboardViews/View/QwertyKeyboard/QwertyKeyboardView.swift b/AzooKeyCore/Sources/KeyboardViews/View/QwertyKeyboard/QwertyKeyboardView.swift index 6797e2a2..7a2a2ab0 100644 --- a/AzooKeyCore/Sources/KeyboardViews/View/QwertyKeyboard/QwertyKeyboardView.swift +++ b/AzooKeyCore/Sources/KeyboardViews/View/QwertyKeyboard/QwertyKeyboardView.swift @@ -15,7 +15,7 @@ struct QwertyKeyboardView: init(keyModels: [[any QwertyKeyModelProtocol]], interfaceSize: CGSize, keyboardOrientation: KeyboardOrientation) { self.keyModels = keyModels - self.tabDesign = TabDependentDesign(width: 10, height: 4, interfaceSize: interfaceSize, layout: .qwerty, orientation: keyboardOrientation) + self.tabDesign = TabDependentDesign(width: 10, height: 4, interfaceSize: interfaceSize, orientation: keyboardOrientation) } private var verticalIndices: Range { diff --git a/AzooKeyCore/Sources/KeyboardViews/View/SpecialTabs/ClipboardHistoryTab.swift b/AzooKeyCore/Sources/KeyboardViews/View/SpecialTabs/ClipboardHistoryTab.swift index 25c22481..a2219807 100644 --- a/AzooKeyCore/Sources/KeyboardViews/View/SpecialTabs/ClipboardHistoryTab.swift +++ b/AzooKeyCore/Sources/KeyboardViews/View/SpecialTabs/ClipboardHistoryTab.swift @@ -209,7 +209,7 @@ struct ClipboardHistoryTab: VStack { listView HStack { - let design = TabDependentDesign(width: 2, height: 7, interfaceSize: variableStates.interfaceSize, layout: .flick, orientation: .vertical) + let design = TabDependentDesign(width: 2, height: 7, interfaceSize: variableStates.interfaceSize, orientation: .vertical) enterKey(design) deleteKey(design) } @@ -218,7 +218,7 @@ struct ClipboardHistoryTab: HStack { listView VStack { - let design = TabDependentDesign(width: 8, height: 2, interfaceSize: variableStates.interfaceSize, layout: .flick, orientation: .horizontal) + let design = TabDependentDesign(width: 8, height: 2, interfaceSize: variableStates.interfaceSize, orientation: .horizontal) deleteKey(design) enterKey(design) } diff --git a/AzooKeyCore/Sources/KeyboardViews/View/SpecialTabs/EmojiTab.swift b/AzooKeyCore/Sources/KeyboardViews/View/SpecialTabs/EmojiTab.swift index 0ddc8dd8..3d9226ca 100644 --- a/AzooKeyCore/Sources/KeyboardViews/View/SpecialTabs/EmojiTab.swift +++ b/AzooKeyCore/Sources/KeyboardViews/View/SpecialTabs/EmojiTab.swift @@ -154,7 +154,7 @@ struct EmojiTab: View { /// 参考用 private var keysHeight: CGFloat { - TabDependentDesign(width: 1, height: 1, interfaceSize: variableStates.interfaceSize, layout: .qwerty, orientation: variableStates.keyboardOrientation).keysHeight + TabDependentDesign(width: 1, height: 1, interfaceSize: variableStates.interfaceSize, orientation: variableStates.keyboardOrientation).keysHeight } private var scrollViewHeight: CGFloat { diff --git a/MainApp/Customize/EditingTenkeyCustardView.swift b/MainApp/Customize/EditingTenkeyCustardView.swift index 9cc65e9c..c49d913d 100644 --- a/MainApp/Customize/EditingTenkeyCustardView.swift +++ b/MainApp/Customize/EditingTenkeyCustardView.swift @@ -150,7 +150,7 @@ struct EditingTenkeyCustardView: CancelableEditor { } Toggle("自動的にタブバーに追加", isOn: $editingItem.addTabBarAutomatically) } - CustardFlickKeysView(models: models, tabDesign: .init(width: layout.rowCount, height: layout.columnCount, interfaceSize: interfaceSize, layout: .flick, orientation: MainAppDesign.keyboardOrientation), layout: layout) {(view: FlickKeyView, x: Int, y: Int) in + CustardFlickKeysView(models: models, tabDesign: .init(width: layout.rowCount, height: layout.columnCount, interfaceSize: interfaceSize, orientation: MainAppDesign.keyboardOrientation), layout: layout) {(view: FlickKeyView, x: Int, y: Int) in if editingItem.emptyKeys.contains(.gridFit(x: x, y: y)) { if !isCovered(at: (x, y)) { Button { From 29af69350ce2e8042954db488aee7dca1552da17 Mon Sep 17 00:00:00 2001 From: ensan-hcl Date: Mon, 23 Oct 2023 11:16:51 +0900 Subject: [PATCH 34/43] Improve feedback and animation --- .../KeyboardBar/ReflectStyleCursorBar.swift | 61 ++++++++++++------- 1 file changed, 40 insertions(+), 21 deletions(-) diff --git a/AzooKeyCore/Sources/KeyboardViews/View/KeyboardBar/ReflectStyleCursorBar.swift b/AzooKeyCore/Sources/KeyboardViews/View/KeyboardBar/ReflectStyleCursorBar.swift index 8d4d7baf..d42da070 100644 --- a/AzooKeyCore/Sources/KeyboardViews/View/KeyboardBar/ReflectStyleCursorBar.swift +++ b/AzooKeyCore/Sources/KeyboardViews/View/KeyboardBar/ReflectStyleCursorBar.swift @@ -73,11 +73,11 @@ private struct CursorBarState: Equatable, Hashable, Sendable { struct ReflectStyleCursorBar: View { init() {} - + @EnvironmentObject private var variableStates: VariableStates @Environment(Extension.Theme.self) private var theme @Environment(\.userActionManager) private var action - + private enum SwipeGestureState { case inactive case tap(l1: CGPoint, l2: CGPoint, l3: CGPoint) @@ -85,22 +85,23 @@ struct ReflectStyleCursorBar? + @MainActor private var fontSize: CGFloat { Design.fonts.resultViewFontSize(userPrefrerence: Extension.SettingProvider.resultViewFontSize) } - + @MainActor fileprivate var itemWidth: CGFloat { fontSize * 1.3 } - + @MainActor fileprivate var viewWidth: CGFloat { variableStates.interfaceSize.width * 0.85 } - + @MainActor var swipeGesture: some Gesture { DragGesture(minimumDistance: 0, coordinateSpace: .global) @@ -180,35 +181,34 @@ struct ReflectStyleCursorBar Font { .system(size: size, weight: symbolsFontWeight, design: .default) } - + @MainActor private var textView: some View { HStack(spacing: .zero) { @@ -232,30 +232,32 @@ struct ReflectStyleCursorBar 20 { // 20以上動いたらダメ + self.longPressTask?.cancel() debug("touch failed") } } touchUpCallBack: { gestureState in - self.action.registerLongPressActionEnd(.init(start: [], repeat: [.moveCursor(-1)])) + // self.action.registerLongPressActionEnd(.init(start: [], repeat: [.moveCursor(-1)])) + self.longPressTask?.cancel() if gestureState.time < 0.4 { withAnimation(.linear(duration: 0.15)) { cursorBarState.move(-1, actionManager: self.action, variableStates: variableStates) } + KeyboardFeedback.tabOrOtherKey() } } ) @@ -271,24 +273,26 @@ struct ReflectStyleCursorBar 20 { // 20以上動いたらダメ + self.longPressTask?.cancel() debug("touch failed") } } touchUpCallBack: { gestureState in - self.action.registerLongPressActionEnd(.init(start: [], repeat: [.moveCursor(1)])) + self.longPressTask?.cancel() if gestureState.time < 0.4 { withAnimation(.linear(duration: 0.15)) { cursorBarState.move(1, actionManager: self.action, variableStates: variableStates) } + KeyboardFeedback.tabOrOtherKey() } } ) } } } - + var body: some View { background .overlay(foregroundButtons) @@ -303,5 +307,20 @@ struct ReflectStyleCursorBar.tabOrOtherKey() + try await Task.sleep(nanoseconds: 0_100_000_000) + } + } + } } From ae2f58509686f5bb26268c5e214e4da7592f5ad8 Mon Sep 17 00:00:00 2001 From: ensan-hcl Date: Mon, 23 Oct 2023 16:07:31 +0900 Subject: [PATCH 35/43] Add localization --- Resources/Localizable.xcstrings | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/Resources/Localizable.xcstrings b/Resources/Localizable.xcstrings index 7bfb0cbd..ce0bb778 100644 --- a/Resources/Localizable.xcstrings +++ b/Resources/Localizable.xcstrings @@ -1443,6 +1443,17 @@ } } }, + "QwertyキーボードでAaキーの代わりにシフトキーを利用します。" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Use shift key instead of Aa key in qwerty keyboards." + } + } + } + }, "unicode変換" : { "extractionState" : "manual", "localizations" : { @@ -3438,6 +3449,17 @@ } } }, + "シフトキーを使う" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Use shift key" + } + } + } + }, "ショートカットを実行" : { "localizations" : { "en" : { From f772b3c0d52d10bab73ea0fb0748bd7cb5af97ae Mon Sep 17 00:00:00 2001 From: ensan-hcl Date: Tue, 24 Oct 2023 16:20:21 +0900 Subject: [PATCH 36/43] =?UTF-8?q?Qwerty=E3=81=AE=E3=82=B5=E3=82=B8?= =?UTF-8?q?=E3=82=A7=E3=82=B9=E3=83=88=E3=81=AB=E3=82=A2=E3=83=8B=E3=83=A1?= =?UTF-8?q?=E3=83=BC=E3=82=B7=E3=83=A7=E3=83=B3=E3=82=92=E8=BF=BD=E5=8A=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../KeyView/QwertyVariationsView.swift | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/AzooKeyCore/Sources/KeyboardViews/View/QwertyKeyboard/KeyView/QwertyVariationsView.swift b/AzooKeyCore/Sources/KeyboardViews/View/QwertyKeyboard/KeyView/QwertyVariationsView.swift index c55d9a64..c950e4fc 100644 --- a/AzooKeyCore/Sources/KeyboardViews/View/QwertyKeyboard/KeyView/QwertyVariationsView.swift +++ b/AzooKeyCore/Sources/KeyboardViews/View/QwertyKeyboard/KeyView/QwertyVariationsView.swift @@ -13,6 +13,7 @@ struct QwertyVariationsView private let model: VariationsModel private let selection: Int? @Environment(Extension.Theme.self) private var theme + @Namespace private var namespace private let tabDesign: TabDependentDesign init(model: VariationsModel, selection: Int?, tabDesign: TabDependentDesign) { @@ -29,17 +30,21 @@ struct QwertyVariationsView HStack(spacing: tabDesign.horizontalSpacing) { ForEach(model.variations.indices, id: \.self) {(index: Int) in ZStack { - Rectangle() - .foregroundStyle(index == selection ? Color.blue : suggestColor) - .frame(width: tabDesign.keyViewWidth, height: tabDesign.keyViewHeight * 0.9, alignment: .center) - .cornerRadius(10.0) - getLabel(model.variations[index].label) + if index == selection { + Rectangle() + .foregroundStyle(.blue) + .cornerRadius(10.0) + .matchedGeometryEffect(id: "focus", in: namespace) + } + getLabel(model.variations[index].label, textColor: index == selection ? .white : theme.suggestLabelTextColor?.color ?? .black) } + .frame(width: tabDesign.keyViewWidth, height: tabDesign.keyViewHeight * 0.9, alignment: .center) } } + .animation(.easeOut(duration: 0.075), value: selection) } - @MainActor private func getLabel(_ labelType: KeyLabelType) -> KeyLabel { - KeyLabel(labelType, width: tabDesign.keyViewWidth, textColor: theme.suggestLabelTextColor?.color ?? .black) + @MainActor private func getLabel(_ labelType: KeyLabelType, textColor: Color) -> KeyLabel { + KeyLabel(labelType, width: tabDesign.keyViewWidth, textColor: textColor) } } From ad1ce7bf842053ff31a777ebd497b1a9d171c8d9 Mon Sep 17 00:00:00 2001 From: ensan-hcl Date: Fri, 27 Oct 2023 16:06:04 +0900 Subject: [PATCH 37/43] =?UTF-8?q?TabManager=E3=81=B8=E3=81=AE=E3=82=A2?= =?UTF-8?q?=E3=82=AF=E3=82=BB=E3=82=B9=E3=81=A7BAD=5FACCESS=E3=81=8C?= =?UTF-8?q?=E7=99=BA=E7=94=9F=E3=81=97=E3=81=A6=E3=81=84=E3=82=8B=E5=95=8F?= =?UTF-8?q?=E9=A1=8C=E3=82=92=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Sources/KeyboardViews/VariableStates.swift | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/AzooKeyCore/Sources/KeyboardViews/VariableStates.swift b/AzooKeyCore/Sources/KeyboardViews/VariableStates.swift index 11caf36f..f736afab 100644 --- a/AzooKeyCore/Sources/KeyboardViews/VariableStates.swift +++ b/AzooKeyCore/Sources/KeyboardViews/VariableStates.swift @@ -109,16 +109,16 @@ public final class VariableStates: ObservableObject { } } } - private(set) public var inputStyle: InputStyle = .direct - private(set) public var tabManager: TabManager - public var keyboardInternalSettingManager: KeyboardInternalSettingManager + @MainActor private(set) public var inputStyle: InputStyle = .direct + @Published private(set) public var tabManager: TabManager + @Published public var keyboardInternalSettingManager: KeyboardInternalSettingManager @Published public var clipboardHistoryManager: ClipboardHistoryManager @Published public var keyboardLanguage: KeyboardLanguage = .ja_JP @Published private(set) public var keyboardOrientation: KeyboardOrientation = .vertical @Published private(set) public var keyboardLayout: KeyboardLayout = .flick - private(set) public var keyboardType: UIKeyboardType = .default + @MainActor private(set) public var keyboardType: UIKeyboardType = .default /// `ResultModel`の変数 @Published public var resultModel = ResultModel() @@ -131,7 +131,7 @@ public final class VariableStates: ObservableObject { @Published public var interfacePosition: CGPoint = .zero /// 外部では利用しないが、`enterKeyState`の更新時に必要になる - private(set) public var returnKeyType: UIReturnKeyType = .default + @MainActor private(set) public var returnKeyType: UIReturnKeyType = .default @Published private(set) var enterKeyState: EnterKeyState = .return(.default) @Published public var barState: BarState = .none @@ -244,7 +244,7 @@ public final class VariableStates: ObservableObject { } } - public func setEnterKeyState(_ state: RoughEnterKeyState) { + @MainActor public func setEnterKeyState(_ state: RoughEnterKeyState) { switch state { case .return: self.enterKeyState = .return(returnKeyType) @@ -266,7 +266,7 @@ public final class VariableStates: ObservableObject { self.setTab(tab, temporary: temporary) } - public func setUIReturnKeyType(type: UIReturnKeyType) { + @MainActor public func setUIReturnKeyType(type: UIReturnKeyType) { self.returnKeyType = type if case let .return(prev) = self.enterKeyState, prev != type { self.setEnterKeyState(.return) @@ -287,7 +287,7 @@ public final class VariableStates: ObservableObject { self.updateResizingState() } - public func setInputStyle(_ style: InputStyle) { + @MainActor public func setInputStyle(_ style: InputStyle) { self.inputStyle = style } From 3d5efefaade2a846b58a25d73ca75a2addb02bc1 Mon Sep 17 00:00:00 2001 From: ensan-hcl Date: Sat, 28 Oct 2023 11:25:52 +0900 Subject: [PATCH 38/43] =?UTF-8?q?=E3=82=BF=E3=83=96=E3=83=90=E3=83=BC?= =?UTF-8?q?=E3=81=AE=E8=87=AA=E5=8B=95=E9=9D=9E=E8=A1=A8=E7=A4=BA=E3=82=92?= =?UTF-8?q?=E9=9A=A0=E3=81=97=E6=A9=9F=E8=83=BD=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../AzooKeyKeyboardViewExtension.swift | 8 ++++++-- .../KeyboardSetting/BoolKeyboardSetting.swift | 17 ++++++++++++++--- ...ionSpecificKeyboardViewSettingProvider.swift | 11 +++++++++-- .../View/KeyboardBar/KeyboardBarView.swift | 10 +++++++++- Keyboard/Display/InputManager.swift | 9 +++++---- MainApp/Setting/SettingTab.swift | 2 +- 6 files changed, 44 insertions(+), 13 deletions(-) diff --git a/AzooKeyCore/Sources/AzooKeyUtils/AzooKeyKeyboardViewExtension.swift b/AzooKeyCore/Sources/AzooKeyUtils/AzooKeyKeyboardViewExtension.swift index 608f5d30..39d77a4c 100644 --- a/AzooKeyCore/Sources/AzooKeyUtils/AzooKeyKeyboardViewExtension.swift +++ b/AzooKeyCore/Sources/AzooKeyUtils/AzooKeyKeyboardViewExtension.swift @@ -90,14 +90,18 @@ public enum AzooKeyKeyboardViewExtension: ApplicationSpecificKeyboardViewExtensi HideResetButtonInOneHandedMode.value } - public static var useSliderStyleCursorBar: Bool { - UseSliderStyleCursorBar.value + public static var useReflectStyleCursorBar: Bool { + UseReflectStyleCursorBar.value } public static var useShiftKey: Bool { UseShiftKey.value } + public static var displayCursorBarAutomatically: Bool { + DisplayCursorBarAutomatically.value + } + public static var canResetLearningForCandidate: Bool { LearningTypeSetting.value.needUsingMemory } diff --git a/AzooKeyCore/Sources/AzooKeyUtils/KeyboardSetting/BoolKeyboardSetting.swift b/AzooKeyCore/Sources/AzooKeyUtils/KeyboardSetting/BoolKeyboardSetting.swift index 83ea01d2..d1794bb2 100644 --- a/AzooKeyCore/Sources/AzooKeyUtils/KeyboardSetting/BoolKeyboardSetting.swift +++ b/AzooKeyCore/Sources/AzooKeyUtils/KeyboardSetting/BoolKeyboardSetting.swift @@ -167,7 +167,7 @@ public extension KeyboardSettingKey where Self == DisplayTabBarButton { static var displayTabBarButton: Self { .init() } } -public struct UseSliderStyleCursorBar: BoolKeyboardSettingKey { +public struct UseReflectStyleCursorBar: BoolKeyboardSettingKey { public static let title: LocalizedStringKey = "新しいカーソルバーを使う" public static let explanation: LocalizedStringKey = "操作性が向上した新しいカーソルバーを有効化します。" public static let defaultValue = false @@ -175,8 +175,19 @@ public struct UseSliderStyleCursorBar: BoolKeyboardSettingKey { public static let key: String = "use_move_cursor_bar_beta" } -public extension KeyboardSettingKey where Self == UseSliderStyleCursorBar { - static var useSliderStyleCursorBar: Self { .init() } +public extension KeyboardSettingKey where Self == UseReflectStyleCursorBar { + static var useReflectStyleCursorBar: Self { .init() } +} + +public struct DisplayCursorBarAutomatically: BoolKeyboardSettingKey { + public static let title: LocalizedStringKey = "カーソルバーを自動表示" + public static let explanation: LocalizedStringKey = "カーソル移動の際にカーソルバーを自動表示します" + public static let defaultValue = false + public static let key: String = "display_cursor_bar_automatically" +} + +public extension KeyboardSettingKey where Self == DisplayCursorBarAutomatically { + static var displayCursorBarAutomatically: Self { .init() } } public struct UseShiftKey: BoolKeyboardSettingKey { diff --git a/AzooKeyCore/Sources/KeyboardViews/ApplicationSpecificKeyboardViewSettingProvider.swift b/AzooKeyCore/Sources/KeyboardViews/ApplicationSpecificKeyboardViewSettingProvider.swift index 5c4aaf0b..11ed50a4 100644 --- a/AzooKeyCore/Sources/KeyboardViews/ApplicationSpecificKeyboardViewSettingProvider.swift +++ b/AzooKeyCore/Sources/KeyboardViews/ApplicationSpecificKeyboardViewSettingProvider.swift @@ -28,11 +28,18 @@ import Foundation static var enableSound: Bool { get } static var enableHaptics: Bool { get } static var enablePasteButton: Bool { get } - static var displayTabBarButton: Bool { get } static var hideResetButtonInOneHandedMode: Bool { get } - static var useSliderStyleCursorBar: Bool { get } static var useShiftKey: Bool { get } + /// タブバーボタンを表示する + /// - note: このオプションは一度削除を決めたが、ユーザから強い要望があったので維持することにした。 + static var displayTabBarButton: Bool { get } + /// 反射スタイルのカーソルバーを利用する + static var useReflectStyleCursorBar: Bool { get } + /// カーソルバーを自動表示する(実験的機能) + /// - note: この機能は実験的に導入しているが、仕様に議論がある。[#346](https://github.com/ensan-hcl/azooKey/issues/346)も参照。 + static var displayCursorBarAutomatically: Bool { get } + static var canResetLearningForCandidate: Bool { get } static func get(_: CustomizableFlickKey) -> KeyFlickSetting.SettingData diff --git a/AzooKeyCore/Sources/KeyboardViews/View/KeyboardBar/KeyboardBarView.swift b/AzooKeyCore/Sources/KeyboardViews/View/KeyboardBar/KeyboardBarView.swift index 0e7fcd99..c7f4d417 100644 --- a/AzooKeyCore/Sources/KeyboardViews/View/KeyboardBar/KeyboardBarView.swift +++ b/AzooKeyCore/Sources/KeyboardViews/View/KeyboardBar/KeyboardBarView.swift @@ -19,7 +19,11 @@ struct KeyboardBarView: Vie @State private var dismissTask: Task<(), any Error>? = nil private var useReflectStyleCursorBar: Bool { - Extension.SettingProvider.useSliderStyleCursorBar + Extension.SettingProvider.useReflectStyleCursorBar + } + + private var displayCursorBarAutomatically: Bool { + Extension.SettingProvider.displayCursorBarAutomatically } init(isResultViewExpanded: Binding) { @@ -58,6 +62,10 @@ struct KeyboardBarView: Vie } private func restartCursorBarDismissTask() { + // 自動非表示はdisplayCursorBarAutomaticallyが有効の場合のみにする。 + guard self.displayCursorBarAutomatically else { + return + } self.dismissTask?.cancel() self.dismissTask = Task { // 10秒待つ diff --git a/Keyboard/Display/InputManager.swift b/Keyboard/Display/InputManager.swift index 3866ba6a..5ab388ab 100644 --- a/Keyboard/Display/InputManager.swift +++ b/Keyboard/Display/InputManager.swift @@ -791,14 +791,14 @@ import UIKit // リザルトバーを表示する return [.setCursorBar(.off), .setTabBar(.off)] } + @KeyboardSetting(.displayCursorBarAutomatically) var displayCursorBarAutomatically // 入力テキストなし if self.composingText.isEmpty { - // 入力がない場合はreturnしておかないと、入力していない時にカーソルを動かせなくなってしまう。 - return [.setCursorBar(.on)] + return displayCursorBarAutomatically ? [.setCursorBar(.on)] : [] } // ライブ変換有効 if liveConversionEnabled { - return [.setCursorBar(.on)] + return displayCursorBarAutomatically ? [.setCursorBar(.on)] : [] } let actualCount = composingText.moveCursorFromCursorPosition(count: count) self.previousSystemOperation = self.displayedTextManager.updateComposingText(composingText: self.composingText, userMovedCount: count, adjustedMovedCount: actualCount) ? .moveCursor : nil @@ -809,7 +809,8 @@ import UIKit /// ユーザが行を跨いでカーソルを動かした場合に利用する func userJumpedCursor() -> [ActionType] { if self.composingText.isEmpty { - return [.setCursorBar(.on)] + @KeyboardSetting(.displayCursorBarAutomatically) var displayCursorBarAutomatically + return displayCursorBarAutomatically ? [.setCursorBar(.on)] : [] } self.stopComposition() return [] diff --git a/MainApp/Setting/SettingTab.swift b/MainApp/Setting/SettingTab.swift index 2c3520aa..bccc8ae4 100644 --- a/MainApp/Setting/SettingTab.swift +++ b/MainApp/Setting/SettingTab.swift @@ -51,7 +51,7 @@ struct SettingTabView: View { } } Section(header: Text("バー")) { - BoolSettingView(.useSliderStyleCursorBar) + BoolSettingView(.useReflectStyleCursorBar) BoolSettingView(.displayTabBarButton) BoolSettingView(.enableClipboardHistoryManagerTab) if SemiStaticStates.shared.hasFullAccess { From 92ba0a34e5c62061c1b54d3edc44e1260731d6b3 Mon Sep 17 00:00:00 2001 From: ensan-hcl Date: Sun, 29 Oct 2023 15:29:30 +0900 Subject: [PATCH 39/43] Update info --- MainApp/UpdateInformationView.swift | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/MainApp/UpdateInformationView.swift b/MainApp/UpdateInformationView.swift index 6a7ce511..ad5d3e8d 100644 --- a/MainApp/UpdateInformationView.swift +++ b/MainApp/UpdateInformationView.swift @@ -16,7 +16,7 @@ struct UpdateInformationView: View { Group { // version 2.2系 Group { - VersionView("2.2", releaseDate: "2023年10月xx日") { + VersionView("2.2", releaseDate: "2023年11月xx日") { if #unavailable(iOS 16) { ParagraphView("お知らせ。") { "バージョン2.3以降でiOS15のサポートを終了します。iOS16以上で引き続きご利用いただけます。ご不便をおかけしますが、よろしくお願いいたします" @@ -30,13 +30,13 @@ struct UpdateInformationView: View { "再変換を大幅に強化しました。" "「連絡先」に登録されている氏名を読み込んで変換に利用できるようになりました" "テキストを選択した際に表示していた「編集」機能を廃止しました" - "カーソルを動かした際、カーソルバーを表示するようにしました" + "英語のQwertyキーボードでシフトキーが利用できるようになりました" "カスタムキーで「次候補」と「A/a」の特殊キーを選べるようになりました" } ParagraphView("デザインを改善しました") { "サジェストをよりはっきりと表示するようにしました" "カーソルバーのデザインを改善しました" - "iPadでのデザインを改善しました" + "iPadでのアプリのデザインを改善しました" } ParagraphView("複数の不具合を修正しました。") ParagraphView("その他辞書の改善を行いました。") From 66f2e4f7e184130ff36ebd6bdebb9c7e36a2266a Mon Sep 17 00:00:00 2001 From: ensan-hcl Date: Sun, 29 Oct 2023 15:35:20 +0900 Subject: [PATCH 40/43] apply swiftlint --fix and swiftlint --format --- .../SimpleKeyView/SimpleKeyModel.swift | 5 ++- .../KeyView/FlickChangeKeyboardKeyModel.swift | 2 +- .../View/KeyboardBar/KeyboardBarView.swift | 2 +- .../KeyboardBar/ReflectStyleCursorBar.swift | 31 +++++++++---------- .../KeyboardBar/SliderStyleCursorBar.swift | 2 +- .../KeyView/QwertyNextCandidateKeyModel.swift | 8 ++--- .../Customize/CodableActionDataEditor.swift | 2 +- .../OpenSourceSoftwaresLicenseView.swift | 2 +- 8 files changed, 26 insertions(+), 28 deletions(-) diff --git a/AzooKeyCore/Sources/KeyboardViews/View/CustomKeybaord/SimpleKeyView/SimpleKeyModel.swift b/AzooKeyCore/Sources/KeyboardViews/View/CustomKeybaord/SimpleKeyView/SimpleKeyModel.swift index 1314062a..0b748c7c 100644 --- a/AzooKeyCore/Sources/KeyboardViews/View/CustomKeybaord/SimpleKeyView/SimpleKeyModel.swift +++ b/AzooKeyCore/Sources/KeyboardViews/View/CustomKeybaord/SimpleKeyView/SimpleKeyModel.swift @@ -89,7 +89,7 @@ struct SimpleKeyModel: Simp func pressActions(variableStates: VariableStates) -> [ActionType] { pressActions } - + func longPressActions(variableStates: VariableStates) -> LongpressActionType { longPressActions } @@ -132,7 +132,7 @@ struct SimpleEnterKeyModel: struct SimpleNextCandidateKeyModel: SimpleKeyModelProtocol { var unpressedKeyColorType: SimpleUnpressedKeyColorType = .normal - + func pressActions(variableStates: VariableStates) -> [ActionType] { if variableStates.resultModel.results.isEmpty { [.input(" ")] @@ -168,7 +168,6 @@ struct SimpleNextCandidateKeyModel: SimpleKeyModelProtocol { func pressActions(variableStates: VariableStates) -> [ActionType] { if SemiStaticStates.shared.needsInputModeSwitchKey { diff --git a/AzooKeyCore/Sources/KeyboardViews/View/FlickKeyboard/KeyView/FlickChangeKeyboardKeyModel.swift b/AzooKeyCore/Sources/KeyboardViews/View/FlickKeyboard/KeyView/FlickChangeKeyboardKeyModel.swift index e17f1be8..48581d84 100644 --- a/AzooKeyCore/Sources/KeyboardViews/View/FlickKeyboard/KeyView/FlickChangeKeyboardKeyModel.swift +++ b/AzooKeyCore/Sources/KeyboardViews/View/FlickKeyboard/KeyView/FlickChangeKeyboardKeyModel.swift @@ -34,7 +34,7 @@ struct FlickChangeKeyboardModel LongpressActionType { + func longPressActions(variableStates _: VariableStates) -> LongpressActionType { .none } diff --git a/AzooKeyCore/Sources/KeyboardViews/View/KeyboardBar/KeyboardBarView.swift b/AzooKeyCore/Sources/KeyboardViews/View/KeyboardBar/KeyboardBarView.swift index c7f4d417..e2cf1584 100644 --- a/AzooKeyCore/Sources/KeyboardViews/View/KeyboardBar/KeyboardBarView.swift +++ b/AzooKeyCore/Sources/KeyboardViews/View/KeyboardBar/KeyboardBarView.swift @@ -16,7 +16,7 @@ struct KeyboardBarView: Vie @Binding private var isResultViewExpanded: Bool @Environment(Extension.Theme.self) private var theme // CursorBarは操作がない場合に非表示にする。これをハンドルするためのタスク - @State private var dismissTask: Task<(), any Error>? = nil + @State private var dismissTask: Task<(), any Error>? private var useReflectStyleCursorBar: Bool { Extension.SettingProvider.useReflectStyleCursorBar diff --git a/AzooKeyCore/Sources/KeyboardViews/View/KeyboardBar/ReflectStyleCursorBar.swift b/AzooKeyCore/Sources/KeyboardViews/View/KeyboardBar/ReflectStyleCursorBar.swift index d42da070..85080ef8 100644 --- a/AzooKeyCore/Sources/KeyboardViews/View/KeyboardBar/ReflectStyleCursorBar.swift +++ b/AzooKeyCore/Sources/KeyboardViews/View/KeyboardBar/ReflectStyleCursorBar.swift @@ -73,11 +73,11 @@ private struct CursorBarState: Equatable, Hashable, Sendable { struct ReflectStyleCursorBar: View { init() {} - + @EnvironmentObject private var variableStates: VariableStates @Environment(Extension.Theme.self) private var theme @Environment(\.userActionManager) private var action - + private enum SwipeGestureState { case inactive case tap(l1: CGPoint, l2: CGPoint, l3: CGPoint) @@ -86,22 +86,22 @@ struct ReflectStyleCursorBar? - + @MainActor private var fontSize: CGFloat { Design.fonts.resultViewFontSize(userPrefrerence: Extension.SettingProvider.resultViewFontSize) } - + @MainActor fileprivate var itemWidth: CGFloat { fontSize * 1.3 } - + @MainActor fileprivate var viewWidth: CGFloat { variableStates.interfaceSize.width * 0.85 } - + @MainActor var swipeGesture: some Gesture { DragGesture(minimumDistance: 0, coordinateSpace: .global) @@ -181,34 +181,34 @@ struct ReflectStyleCursorBar Font { .system(size: size, weight: symbolsFontWeight, design: .default) } - + @MainActor private var textView: some View { HStack(spacing: .zero) { @@ -232,7 +232,7 @@ struct ReflectStyleCursorBar swipeGestureState = .moving(l1: value.location, l2: l1, l3: l2, count: count) } } - .onEnded {value in + .onEnded {_ in swipeGestureState = .inactive } } diff --git a/AzooKeyCore/Sources/KeyboardViews/View/QwertyKeyboard/KeyView/QwertyNextCandidateKeyModel.swift b/AzooKeyCore/Sources/KeyboardViews/View/QwertyKeyboard/KeyView/QwertyNextCandidateKeyModel.swift index 606a394e..12e8955e 100644 --- a/AzooKeyCore/Sources/KeyboardViews/View/QwertyKeyboard/KeyView/QwertyNextCandidateKeyModel.swift +++ b/AzooKeyCore/Sources/KeyboardViews/View/QwertyKeyboard/KeyView/QwertyNextCandidateKeyModel.swift @@ -13,13 +13,13 @@ import SwiftUI struct QwertyNextCandidateKeyModel: QwertyKeyModelProtocol { let keySizeType: QwertyKeySizeType = .space - + let needSuggestView: Bool = false - + let variationsModel: VariationsModel = .init([]) - + let unpressedKeyColorType: QwertyUnpressedKeyColorType = .normal - + static var shared: Self { QwertyNextCandidateKeyModel() } func pressActions(variableStates: VariableStates) -> [ActionType] { diff --git a/MainApp/Customize/CodableActionDataEditor.swift b/MainApp/Customize/CodableActionDataEditor.swift index 637f405d..8067b2b3 100644 --- a/MainApp/Customize/CodableActionDataEditor.swift +++ b/MainApp/Customize/CodableActionDataEditor.swift @@ -31,7 +31,7 @@ extension CodableActionData { case .paste: return "ペーストする" case .moveTab: return "タブの移動" case .replaceLastCharacters: return "文字を置換" - case let .selectCandidate(selection): + case let .selectCandidate(selection): return switch selection { case .first: "最初の候補を選択" case .last: "最後の候補を選択" diff --git a/MainApp/Setting/OpenSourceSoftwaresLicenseView.swift b/MainApp/Setting/OpenSourceSoftwaresLicenseView.swift index de18234d..504995f3 100644 --- a/MainApp/Setting/OpenSourceSoftwaresLicenseView.swift +++ b/MainApp/Setting/OpenSourceSoftwaresLicenseView.swift @@ -208,7 +208,7 @@ private struct FunnyAzooKeyIcon: View { init(stage: Stage = .normal) { self._stage = .init(initialValue: stage) } - + struct NormalAnimationValue { // degrees var angle: Double = -10 From 8aab6e363048b05eddd9cea4f37ea28235cd8968 Mon Sep 17 00:00:00 2001 From: ensan-hcl Date: Tue, 31 Oct 2023 17:19:49 +0900 Subject: [PATCH 41/43] =?UTF-8?q?Slack=E3=81=A7=E7=B5=B5=E6=96=87=E5=AD=97?= =?UTF-8?q?=E3=81=8C=E4=BA=8C=E9=87=8D=E3=81=AB=E5=85=A5=E5=8A=9B=E3=81=95?= =?UTF-8?q?=E3=82=8C=E5=BE=97=E3=82=8B=E5=95=8F=E9=A1=8C=E3=82=92=E4=BF=AE?= =?UTF-8?q?=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Keyboard/Display/DisplayedTextManager.swift | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/Keyboard/Display/DisplayedTextManager.swift b/Keyboard/Display/DisplayedTextManager.swift index 8e8060e2..229357fc 100644 --- a/Keyboard/Display/DisplayedTextManager.swift +++ b/Keyboard/Display/DisplayedTextManager.swift @@ -280,7 +280,17 @@ import UIKit // (挿入): 愛[|してる] // (挿入): 愛[|してる] // (移動): 愛[してる|] - // 選択中でない場合、削除する + // (例3): [愛してる|] (「愛してる」をライブ変換しており、そのまま確定) + // (何もしない) + defer { + self.composingText = composingText + self.displayedLiveConversionText = nil + } + // 例3のケース + if composingText.isEmpty && completedPrefix == self.displayedLiveConversionText { + return + } + // 選択中でない場合、必要なだけ削除を実行する if !isSelected { let count = self.displayedLiveConversionText?.count ?? self.composingText.convertTargetCursorPosition self.deleteBackward(count: count) @@ -289,8 +299,6 @@ import UIKit let cursorPosition = self.composingText.convertTargetCursorPosition - delta self.insertText(completedPrefix + String(self.composingText.convertTargetBeforeCursor.suffix(cursorPosition))) self.moveCursor(count: composingText.convertTargetCursorPosition - cursorPosition) - self.composingText = composingText - self.displayedLiveConversionText = nil } } } From 25f2ec04083cd90b7c497074e8ee8d2eae527981 Mon Sep 17 00:00:00 2001 From: ensan-hcl Date: Tue, 31 Oct 2023 17:42:49 +0900 Subject: [PATCH 42/43] Version 2.2 will be released 11/3 --- MainApp/UpdateInformationView.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MainApp/UpdateInformationView.swift b/MainApp/UpdateInformationView.swift index ad5d3e8d..f54e7634 100644 --- a/MainApp/UpdateInformationView.swift +++ b/MainApp/UpdateInformationView.swift @@ -16,7 +16,7 @@ struct UpdateInformationView: View { Group { // version 2.2系 Group { - VersionView("2.2", releaseDate: "2023年11月xx日") { + VersionView("2.2", releaseDate: "2023年11月3日") { if #unavailable(iOS 16) { ParagraphView("お知らせ。") { "バージョン2.3以降でiOS15のサポートを終了します。iOS16以上で引き続きご利用いただけます。ご不便をおかけしますが、よろしくお願いいたします" From 44e386d9a9e8591022b0034c461dcc146bf5373e Mon Sep 17 00:00:00 2001 From: Miwa / Ensan <63481257+ensan-hcl@users.noreply.github.com> Date: Thu, 2 Nov 2023 19:34:22 +0900 Subject: [PATCH 43/43] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 6937b117..58d3b4cd 100644 --- a/README.md +++ b/README.md @@ -38,7 +38,7 @@ azooKeyの辞書ファイルは任意に置き換えることができます。 不明な点は気軽にIssue等でご質問ください。 ## 今後のリリース -* 現在、Version 2.2に向けた作業を行っています。 +* 現在、Version 2.3に向けた作業を行っています。 ## azooKeyを支援する GitHub Sponsorsをご利用ください。