- controller navigation preparations
- disable tilt button for pencil - widget picker UI improvement & fixes - allow triggers to be controller mouse buttons
This commit is contained in:
@@ -10,17 +10,26 @@ import SwiftUI
|
||||
import Combine
|
||||
import UIKit
|
||||
|
||||
public enum RadialMenuItem {
|
||||
case settings
|
||||
case hostView
|
||||
case gameProfiles
|
||||
case exit
|
||||
}
|
||||
|
||||
@available(iOS 13.0, *)
|
||||
struct RadialMenuItem: Identifiable, Equatable {
|
||||
struct RadialMenuSector: Identifiable, Equatable {
|
||||
let id = UUID()
|
||||
let title: String
|
||||
let subtitle: String
|
||||
let systemImageName: String
|
||||
let item: RadialMenuItem
|
||||
|
||||
init(title: String, subtitle: String, systemImageName: String) {
|
||||
init(title: String, subtitle: String, systemImageName: String, item: RadialMenuItem) {
|
||||
self.title = title
|
||||
self.subtitle = subtitle
|
||||
self.systemImageName = systemImageName
|
||||
self.item = item
|
||||
}
|
||||
}
|
||||
|
||||
@@ -85,9 +94,9 @@ final class RadialMenuSelectionState: ObservableObject {
|
||||
return nil
|
||||
}
|
||||
|
||||
let clockwiseDegreesFromTop = positiveRemainder(atan2(Double(x), Double(y)) * 180 / .pi, 360)
|
||||
let clockwiseDegreesFromWest = positiveRemainder(atan2(Double(y), -Double(x)) * 180 / .pi, 360)
|
||||
let segmentDegrees = 360 / Double(itemCount)
|
||||
let centeredDegrees = positiveRemainder(clockwiseDegreesFromTop + segmentDegrees / 2, 360)
|
||||
let centeredDegrees = positiveRemainder(clockwiseDegreesFromWest + segmentDegrees / 2, 360)
|
||||
return min(Int(centeredDegrees / segmentDegrees), itemCount - 1)
|
||||
}
|
||||
|
||||
@@ -99,7 +108,7 @@ final class RadialMenuSelectionState: ObservableObject {
|
||||
|
||||
@available(iOS 13.0, *)
|
||||
struct RadialMenuView: View {
|
||||
let items: [RadialMenuItem]
|
||||
let sectors: [RadialMenuSector]
|
||||
var selectedIndex: Int?
|
||||
var isTouchSelectionEnabled: Bool
|
||||
var style: RadialMenuStyle
|
||||
@@ -119,31 +128,31 @@ struct RadialMenuView: View {
|
||||
return selectedIndex
|
||||
}
|
||||
|
||||
private var selectedItem: RadialMenuItem? {
|
||||
private var selectedItem: RadialMenuSector? {
|
||||
guard let selectedIndex = effectiveSelectedIndex,
|
||||
items.indices.contains(selectedIndex) else {
|
||||
return items.first
|
||||
sectors.indices.contains(selectedIndex) else {
|
||||
return sectors.first
|
||||
}
|
||||
return items[selectedIndex]
|
||||
return sectors[selectedIndex]
|
||||
}
|
||||
|
||||
init(
|
||||
items: [RadialMenuItem],
|
||||
sectors: [RadialMenuSector],
|
||||
selectedIndex: Int? = nil,
|
||||
isTouchSelectionEnabled: Bool = true,
|
||||
style: RadialMenuStyle = RadialMenuStyle(),
|
||||
selectionState: RadialMenuSelectionState = RadialMenuSelectionState()
|
||||
) {
|
||||
self.items = items
|
||||
self.sectors = sectors
|
||||
self.selectedIndex = selectedIndex
|
||||
self.isTouchSelectionEnabled = isTouchSelectionEnabled
|
||||
self.style = style
|
||||
self.joystickSelectionState = selectionState
|
||||
self.joystickSelectionState.configureItemCount(items.count)
|
||||
self.joystickSelectionState.configureItemCount(sectors.count)
|
||||
}
|
||||
|
||||
func updateSelection(xOffset: Float, yOffset: Float) {
|
||||
joystickSelectionState.configureItemCount(items.count)
|
||||
joystickSelectionState.configureItemCount(sectors.count)
|
||||
joystickSelectionState.updateSelection(xOffset: xOffset, yOffset: yOffset)
|
||||
}
|
||||
|
||||
@@ -155,10 +164,10 @@ struct RadialMenuView: View {
|
||||
let innerRadius = outerRadius * (1 - style.ringWidthRatio)
|
||||
|
||||
ZStack {
|
||||
ForEach(items.indices, id: \.self) { index in
|
||||
ForEach(sectors.indices, id: \.self) { index in
|
||||
RadialMenuSegmentShape(
|
||||
index: index,
|
||||
count: items.count,
|
||||
count: sectors.count,
|
||||
innerRadiusRatio: 1 - style.ringWidthRatio,
|
||||
gapWidth: style.segmentGapWidth
|
||||
)
|
||||
@@ -166,7 +175,7 @@ struct RadialMenuView: View {
|
||||
.overlay(
|
||||
RadialMenuSegmentShape(
|
||||
index: index,
|
||||
count: items.count,
|
||||
count: sectors.count,
|
||||
innerRadiusRatio: 1 - style.ringWidthRatio,
|
||||
gapWidth: style.segmentGapWidth
|
||||
)
|
||||
@@ -181,13 +190,13 @@ struct RadialMenuView: View {
|
||||
.frame(width: innerRadius * 2, height: innerRadius * 2)
|
||||
.shadow(color: style.shadowColor, radius: 10, x: 0, y: 3)
|
||||
|
||||
ForEach(items.indices, id: \.self) { index in
|
||||
let item = items[index]
|
||||
ForEach(sectors.indices, id: \.self) { index in
|
||||
let item = sectors[index]
|
||||
Image(systemName: item.systemImageName)
|
||||
.font(.system(size: max(diameter * style.segmentIconScale, 18), weight: .medium))
|
||||
.foregroundColor(index == effectiveSelectedIndex ? style.selectedIconColor : style.iconColor)
|
||||
.scaleEffect(index == effectiveSelectedIndex ? 1.18 : 1)
|
||||
.position(iconPosition(index: index, count: items.count, center: center, radius: (outerRadius + innerRadius) / 2))
|
||||
.position(iconPosition(index: index, count: sectors.count, center: center, radius: (outerRadius + innerRadius) / 2))
|
||||
.animation(.spring(response: 0.24, dampingFraction: 0.72), value: effectiveSelectedIndex)
|
||||
}
|
||||
|
||||
@@ -218,7 +227,7 @@ struct RadialMenuView: View {
|
||||
}
|
||||
|
||||
private func index(for location: CGPoint, center: CGPoint, innerRadius: CGFloat, outerRadius: CGFloat) -> Int? {
|
||||
guard !items.isEmpty else { return nil }
|
||||
guard !sectors.isEmpty else { return nil }
|
||||
|
||||
let dx = location.x - center.x
|
||||
let dy = location.y - center.y
|
||||
@@ -227,17 +236,16 @@ struct RadialMenuView: View {
|
||||
return nil
|
||||
}
|
||||
|
||||
let rawDegrees = atan2(dy, dx) * 180 / .pi
|
||||
let clockwiseDegreesFromTop = positiveRemainder(rawDegrees + 450, 360)
|
||||
let segmentDegrees = 360 / Double(items.count)
|
||||
let centeredDegrees = positiveRemainder(clockwiseDegreesFromTop + segmentDegrees / 2, 360)
|
||||
return min(Int(centeredDegrees / segmentDegrees), items.count - 1)
|
||||
let clockwiseDegreesFromWest = positiveRemainder(atan2(Double(-dy), Double(-dx)) * 180 / Double.pi, 360)
|
||||
let segmentDegrees = 360 / Double(sectors.count)
|
||||
let centeredDegrees = positiveRemainder(clockwiseDegreesFromWest + segmentDegrees / 2, 360)
|
||||
return min(Int(centeredDegrees / segmentDegrees), sectors.count - 1)
|
||||
}
|
||||
|
||||
private func iconPosition(index: Int, count: Int, center: CGPoint, radius: CGFloat) -> CGPoint {
|
||||
guard count > 0 else { return center }
|
||||
let segmentDegrees = 360 / Double(count)
|
||||
let angleDegrees = -90 + Double(index) * segmentDegrees
|
||||
let angleDegrees = 180 + Double(index) * segmentDegrees
|
||||
let radians = angleDegrees * .pi / 180
|
||||
return CGPoint(
|
||||
x: center.x + CGFloat(cos(radians)) * radius,
|
||||
@@ -253,7 +261,7 @@ struct RadialMenuView: View {
|
||||
|
||||
@available(iOS 13.0, *)
|
||||
private struct RadialMenuCenterView: View {
|
||||
let item: RadialMenuItem?
|
||||
let item: RadialMenuSector?
|
||||
let style: RadialMenuStyle
|
||||
let diameter: CGFloat
|
||||
|
||||
@@ -298,7 +306,7 @@ private struct RadialMenuSegmentShape: Shape {
|
||||
let outerRadius = min(rect.width, rect.height) / 2
|
||||
let innerRadius = outerRadius * innerRadiusRatio
|
||||
let segmentDegrees = 360 / Double(count)
|
||||
let centerDegrees = -90 + Double(index) * segmentDegrees
|
||||
let centerDegrees = 180 + Double(index) * segmentDegrees
|
||||
let startBoundaryDegrees = centerDegrees - segmentDegrees / 2
|
||||
let endBoundaryDegrees = centerDegrees + segmentDegrees / 2
|
||||
let halfGap = min(gapWidth / 2, max(innerRadius - 1, 0))
|
||||
@@ -379,19 +387,20 @@ struct RadialMenuDemoView: View {
|
||||
@SwiftUI.State private var isTouchSelectionEnabled = true
|
||||
|
||||
static let menuItems = [
|
||||
RadialMenuItem(title: "Settings Menu".localized, subtitle: "", systemImageName: "sidebar.left"),
|
||||
RadialMenuItem(title: "Host View".localized, subtitle: "", systemImageName: PublicUtils.liquidGlassEnabled ? "macwindow.on.rectangle" : "tv"),
|
||||
RadialMenuItem(title: "Game Profiles".localized, subtitle: "", systemImageName: "gamecontroller.circle"),
|
||||
RadialMenuSector(title: "Settings Menu".localized, subtitle: "", systemImageName: "sidebar.left", item: .settings),
|
||||
RadialMenuSector(title: "Host View".localized, subtitle: "", systemImageName: PublicUtils.liquidGlassEnabled ? "macwindow.on.rectangle" : "tv", item: .hostView),
|
||||
RadialMenuSector(title: "Game Profiles".localized, subtitle: "", systemImageName: "gamecontroller.circle", item: .gameProfiles),
|
||||
RadialMenuSector(title: "Exit/Disconnect".localized, subtitle: "", systemImageName: "personalhotspot.slash", item: .gameProfiles),
|
||||
]
|
||||
|
||||
private var visibleItems: [RadialMenuItem] {
|
||||
private var visibleItems: [RadialMenuSector] {
|
||||
Array(Self.menuItems.prefix(itemCount))
|
||||
}
|
||||
|
||||
var body: some View {
|
||||
VStack(spacing: 28) {
|
||||
RadialMenuView(
|
||||
items: visibleItems,
|
||||
sectors: visibleItems,
|
||||
selectedIndex: isTouchSelectionEnabled ? nil : 2,
|
||||
isTouchSelectionEnabled: isTouchSelectionEnabled
|
||||
)
|
||||
@@ -421,7 +430,7 @@ struct RadialMenuView_Previews: PreviewProvider {
|
||||
.previewLayout(.sizeThatFits)
|
||||
|
||||
RadialMenuView(
|
||||
items: Array(RadialMenuDemoView.menuItems.prefix(6)),
|
||||
sectors: Array(RadialMenuDemoView.menuItems.prefix(6)),
|
||||
selectedIndex: 1,
|
||||
isTouchSelectionEnabled: false
|
||||
)
|
||||
|
||||
@@ -73,6 +73,7 @@ struct Key: Identifiable {
|
||||
let visualStyle: KeyVisualStyle
|
||||
let label: String
|
||||
let width: CGFloat
|
||||
let labelInsets: EdgeInsets
|
||||
let sfSymbolName: String?
|
||||
let winCmdString: String?
|
||||
let macCmdString: String?
|
||||
@@ -85,6 +86,7 @@ struct Key: Identifiable {
|
||||
identity: String? = nil,
|
||||
visualStyle: KeyVisualStyle = .standard,
|
||||
width: CGFloat,
|
||||
labelInsets: EdgeInsets = EdgeInsets(top: 3, leading: 6, bottom: 3, trailing: 6),
|
||||
sfSymbolName: String? = nil,
|
||||
winCmdString: String? = nil,
|
||||
macCmdString: String? = nil,
|
||||
@@ -94,6 +96,7 @@ struct Key: Identifiable {
|
||||
self.label = label
|
||||
self.identity = identity
|
||||
self.width = width
|
||||
self.labelInsets = labelInsets
|
||||
self.visualStyle = visualStyle
|
||||
self.sfSymbolName = sfSymbolName
|
||||
self.winCmdString = winCmdString
|
||||
@@ -1041,8 +1044,8 @@ struct VirtualKeyboardView: View {
|
||||
Key(
|
||||
label: LocalizationHelper.localizedString(forKey: "Wheel\nUp"),
|
||||
width: unit,
|
||||
winCmdString: "WHEELDOWN",
|
||||
macCmdString: "WHEELDOWN",
|
||||
winCmdString: "WHEELUP",
|
||||
macCmdString: "WHEELUP",
|
||||
winKeyCode: 0xFF,
|
||||
macKeyCode: 0xFF
|
||||
)
|
||||
@@ -1052,8 +1055,8 @@ struct VirtualKeyboardView: View {
|
||||
Key(
|
||||
label: LocalizationHelper.localizedString(forKey: "Wheel\nDown"),
|
||||
width: unit,
|
||||
winCmdString: "WHEELUP",
|
||||
macCmdString: "WHEELUP",
|
||||
winCmdString: "WHEELDOWN",
|
||||
macCmdString: "WHEELDOWN",
|
||||
winKeyCode: 0xFF,
|
||||
macKeyCode: 0xFF
|
||||
)
|
||||
@@ -1065,8 +1068,8 @@ struct VirtualKeyboardView: View {
|
||||
Key(
|
||||
label: LocalizationHelper.localizedString(forKey: "Wheel\nUp"),
|
||||
width: unit,
|
||||
winCmdString: "WHEELDOWN",
|
||||
macCmdString: "WHEELDOWN",
|
||||
winCmdString: "WHEELUP",
|
||||
macCmdString: "WHEELUP",
|
||||
winKeyCode: 0xFF,
|
||||
macKeyCode: 0xFF
|
||||
)
|
||||
@@ -1076,8 +1079,8 @@ struct VirtualKeyboardView: View {
|
||||
Key(
|
||||
label: LocalizationHelper.localizedString(forKey: "Wheel\nDown"),
|
||||
width: unit,
|
||||
winCmdString: "WHEELUP",
|
||||
macCmdString: "WHEELUP",
|
||||
winCmdString: "WHEELDOWN",
|
||||
macCmdString: "WHEELDOWN",
|
||||
winKeyCode: 0xFF,
|
||||
macKeyCode: 0xFF
|
||||
)
|
||||
@@ -1364,11 +1367,15 @@ struct KeyView: View {
|
||||
key.keyCode(for: keyboardType)
|
||||
}
|
||||
|
||||
private var keyCornerRadius: CGFloat {
|
||||
11.0
|
||||
}
|
||||
|
||||
private var typingHighlightFill: LinearGradient {
|
||||
LinearGradient(
|
||||
gradient: Gradient(colors: [
|
||||
Color(red: 0.78, green: 0.84, blue: 0.92).opacity(0.95),
|
||||
Color(red: 0.66, green: 0.74, blue: 0.85).opacity(0.88)
|
||||
Color(red: 0.92, green: 0.945, blue: 0.98),
|
||||
Color(red: 0.76, green: 0.82, blue: 0.90)
|
||||
]),
|
||||
startPoint: .topLeading,
|
||||
endPoint: .bottomTrailing
|
||||
@@ -1376,31 +1383,64 @@ struct KeyView: View {
|
||||
}
|
||||
|
||||
private var typingHighlightStroke: Color {
|
||||
Color(red: 0.42, green: 0.52, blue: 0.66).opacity(0.78)
|
||||
Color(red: 0.47, green: 0.58, blue: 0.73).opacity(0.62)
|
||||
}
|
||||
|
||||
private var keyFillColor: Color {
|
||||
private var keyFillGradient: LinearGradient {
|
||||
switch key.visualStyle {
|
||||
case .standard:
|
||||
return Color.gray.opacity(0.2)
|
||||
return LinearGradient(
|
||||
gradient: Gradient(colors: [
|
||||
Color(red: 0.990, green: 0.988, blue: 0.984),
|
||||
Color(red: 0.920, green: 0.920, blue: 0.910)
|
||||
]),
|
||||
startPoint: .topLeading,
|
||||
endPoint: .bottomTrailing
|
||||
)
|
||||
case .directionPad:
|
||||
return usesDirectionPadBaseStyle
|
||||
? Color(red: 0.16, green: 0.72, blue: 0.66).opacity(0.2)
|
||||
: Color.gray.opacity(0.2)
|
||||
if usesDirectionPadBaseStyle {
|
||||
return LinearGradient(
|
||||
gradient: Gradient(colors: [
|
||||
Color(red: 0.88, green: 0.98, blue: 0.96),
|
||||
Color(red: 0.73, green: 0.91, blue: 0.88)
|
||||
]),
|
||||
startPoint: .topLeading,
|
||||
endPoint: .bottomTrailing
|
||||
)
|
||||
}
|
||||
return LinearGradient(
|
||||
gradient: Gradient(colors: [
|
||||
Color(red: 0.990, green: 0.988, blue: 0.984),
|
||||
Color(red: 0.920, green: 0.920, blue: 0.910)
|
||||
]),
|
||||
startPoint: .topLeading,
|
||||
endPoint: .bottomTrailing
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private var keyStrokeColor: Color {
|
||||
switch key.visualStyle {
|
||||
case .standard:
|
||||
return Color.gray.opacity(0.2)
|
||||
return Color(red: 0.66, green: 0.66, blue: 0.64).opacity(0.36)
|
||||
case .directionPad:
|
||||
return usesDirectionPadBaseStyle
|
||||
? Color(red: 0.08, green: 0.49, blue: 0.45).opacity(0.55)
|
||||
: Color.gray.opacity(0.2)
|
||||
? Color(red: 0.18, green: 0.56, blue: 0.52).opacity(0.52)
|
||||
: Color(red: 0.66, green: 0.66, blue: 0.64).opacity(0.36)
|
||||
}
|
||||
}
|
||||
|
||||
private var pressedFillGradient: LinearGradient {
|
||||
LinearGradient(
|
||||
gradient: Gradient(colors: [
|
||||
Color(red: 0.84, green: 0.87, blue: 0.91),
|
||||
Color(red: 0.72, green: 0.76, blue: 0.82)
|
||||
]),
|
||||
startPoint: .topLeading,
|
||||
endPoint: .bottomTrailing
|
||||
)
|
||||
}
|
||||
|
||||
private var foregroundColor: Color {
|
||||
if mode == .typing && (highlightStyle != .none || isPressed) {
|
||||
return Color.black.opacity(0.72)
|
||||
@@ -1427,56 +1467,54 @@ struct KeyView: View {
|
||||
Image(systemName: name)
|
||||
.font(.system(size: fontSize))
|
||||
.foregroundColor(.black)
|
||||
.frame(maxWidth: .infinity, maxHeight: .infinity)
|
||||
} else {
|
||||
Text(key.label)
|
||||
.font(.system(size: fontSize, weight: .regular, design: .rounded))
|
||||
.foregroundColor(.black)
|
||||
.lineLimit(key.label.contains("\n") ? 2 : 1)
|
||||
.minimumScaleFactor(0.45)
|
||||
.allowsTightening(true)
|
||||
.multilineTextAlignment(.center)
|
||||
.frame(maxWidth: .infinity, maxHeight: .infinity)
|
||||
}
|
||||
}
|
||||
|
||||
private var backgroundColor: Color {
|
||||
if highlightStyle != .none {
|
||||
return Color.clear
|
||||
}
|
||||
|
||||
if isPressed || isActive {
|
||||
return Color.gray.opacity(0.4)
|
||||
}
|
||||
return keyFillColor
|
||||
}
|
||||
|
||||
@ViewBuilder
|
||||
private var keyBackground: some View {
|
||||
if mode == .typing, (highlightStyle != .none || isPressed) {
|
||||
RoundedRectangle(cornerRadius: 6, style: .continuous)
|
||||
RoundedRectangle(cornerRadius: keyCornerRadius, style: .continuous)
|
||||
.fill(typingHighlightFill)
|
||||
} else if isPressed || isActive {
|
||||
RoundedRectangle(cornerRadius: keyCornerRadius, style: .continuous)
|
||||
.fill(pressedFillGradient)
|
||||
} else if highlightStyle == .pad {
|
||||
RoundedRectangle(cornerRadius: 6, style: .continuous)
|
||||
RoundedRectangle(cornerRadius: keyCornerRadius, style: .continuous)
|
||||
.fill(
|
||||
LinearGradient(
|
||||
gradient: Gradient(colors: [
|
||||
Color(red: 0.82, green: 0.84, blue: 1.00).opacity(0.92),
|
||||
Color(red: 0.56, green: 0.60, blue: 0.94).opacity(0.84)
|
||||
Color(red: 0.89, green: 0.90, blue: 1.00),
|
||||
Color(red: 0.64, green: 0.68, blue: 0.96)
|
||||
]),
|
||||
startPoint: .topLeading,
|
||||
endPoint: .bottomTrailing
|
||||
)
|
||||
)
|
||||
} else if highlightStyle == .single {
|
||||
RoundedRectangle(cornerRadius: 6, style: .continuous)
|
||||
RoundedRectangle(cornerRadius: keyCornerRadius, style: .continuous)
|
||||
.fill(
|
||||
LinearGradient(
|
||||
gradient: Gradient(colors: [
|
||||
Color(red: 1.00, green: 0.96, blue: 0.74),
|
||||
Color(red: 0.95, green: 0.78, blue: 0.32)
|
||||
Color(red: 1.00, green: 0.98, blue: 0.78),
|
||||
Color(red: 0.96, green: 0.80, blue: 0.36)
|
||||
]),
|
||||
startPoint: .topLeading,
|
||||
endPoint: .bottomTrailing
|
||||
)
|
||||
)
|
||||
} else {
|
||||
RoundedRectangle(cornerRadius: 6, style: .continuous)
|
||||
.fill(backgroundColor)
|
||||
RoundedRectangle(cornerRadius: keyCornerRadius, style: .continuous)
|
||||
.fill(keyFillGradient)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1493,15 +1531,33 @@ struct KeyView: View {
|
||||
return keyStrokeColor
|
||||
}
|
||||
|
||||
private var keyShadowColor: Color {
|
||||
if isPressed || isActive {
|
||||
return Color.black.opacity(0.08)
|
||||
}
|
||||
if highlightStyle != .none {
|
||||
return Color.black.opacity(0.08)
|
||||
}
|
||||
return Color.black.opacity(PublicUtils.isIPhone ? 0.13 : 0.15)
|
||||
}
|
||||
|
||||
var body: some View {
|
||||
keyContent
|
||||
.padding(key.labelInsets)
|
||||
.foregroundColor(foregroundColor)
|
||||
.frame(width: key.width, height: height)
|
||||
.background(keyBackground)
|
||||
.overlay(
|
||||
RoundedRectangle(cornerRadius: 6)
|
||||
.stroke(borderColor, lineWidth: highlightStyle == .none ? (key.visualStyle == .standard ? 1 : 1.5) : 1.5)
|
||||
RoundedRectangle(cornerRadius: keyCornerRadius, style: .continuous)
|
||||
.stroke(Color.white.opacity(isPressed || isActive ? 0.22 : 0.45), lineWidth: 0.76)
|
||||
.padding(1)
|
||||
)
|
||||
.overlay(
|
||||
RoundedRectangle(cornerRadius: keyCornerRadius, style: .continuous)
|
||||
.stroke(borderColor, lineWidth: highlightStyle == .none ? (key.visualStyle == .standard ? (PublicUtils.isIPhone ? 1.15 : 0.7) : 1.1) : 1.25)
|
||||
|
||||
)
|
||||
.shadow(color: keyShadowColor, radius: isPressed || isActive ? 1 : 3, x: 0, y: isPressed || isActive ? 1 : 2)
|
||||
.simultaneousGesture(
|
||||
DragGesture(minimumDistance: 0)
|
||||
.onChanged { _ in
|
||||
|
||||
@@ -694,6 +694,36 @@ struct WidgetPickerView: View {
|
||||
allowsShortcutCombo: false,
|
||||
forcedComboMode: nil
|
||||
),
|
||||
FunctionalButtonOption(
|
||||
localizationKey: "=absoluteTouchDrag",
|
||||
cmd: "ABSTCHDRAG",
|
||||
tip: LocalizationHelper.localizedString(forKey: "Replace mouse button action in single point touch mode with another button temporarily"),
|
||||
allowsKeyboardCombination: true,
|
||||
allowsGamepadCombination: true,
|
||||
allowsSkillCombo: true,
|
||||
allowsShortcutCombo: false,
|
||||
forcedComboMode: .skill
|
||||
),
|
||||
FunctionalButtonOption(
|
||||
localizationKey: "=magnifier",
|
||||
cmd: "MAGNIFIER",
|
||||
tip: LocalizationHelper.localizedString(forKey: "magnifierTip"),
|
||||
allowsKeyboardCombination: false,
|
||||
allowsGamepadCombination: false,
|
||||
allowsSkillCombo: false,
|
||||
allowsShortcutCombo: false,
|
||||
forcedComboMode: .skill
|
||||
),
|
||||
FunctionalButtonOption(
|
||||
localizationKey: "=dummyPad",
|
||||
cmd: "DUMMYPAD",
|
||||
tip: LocalizationHelper.localizedString(forKey: "dummyPadTip"),
|
||||
allowsKeyboardCombination: false,
|
||||
allowsGamepadCombination: false,
|
||||
allowsSkillCombo: false,
|
||||
allowsShortcutCombo: false,
|
||||
forcedComboMode: .skill
|
||||
),
|
||||
FunctionalButtonOption(
|
||||
localizationKey: "=pressureCurve",
|
||||
cmd: "PRESSURECURVE",
|
||||
@@ -745,34 +775,14 @@ struct WidgetPickerView: View {
|
||||
forcedComboMode: nil
|
||||
),
|
||||
FunctionalButtonOption(
|
||||
localizationKey: "=absoluteTouchDrag",
|
||||
cmd: "ABSTCHDRAG",
|
||||
tip: LocalizationHelper.localizedString(forKey: "Replace mouse button action in single point touch mode with another button temporarily"),
|
||||
allowsKeyboardCombination: true,
|
||||
allowsGamepadCombination: true,
|
||||
allowsSkillCombo: true,
|
||||
allowsShortcutCombo: false,
|
||||
forcedComboMode: .skill
|
||||
),
|
||||
FunctionalButtonOption(
|
||||
localizationKey: "=magnifier",
|
||||
cmd: "MAGNIFIER",
|
||||
tip: LocalizationHelper.localizedString(forKey: "magnifierTip"),
|
||||
localizationKey: "=disableTilt",
|
||||
cmd: "DISABLETILT",
|
||||
tip: LocalizationHelper.localizedString(forKey: "Disable tilt for apple pencil"),
|
||||
allowsKeyboardCombination: false,
|
||||
allowsGamepadCombination: false,
|
||||
allowsSkillCombo: false,
|
||||
allowsShortcutCombo: false,
|
||||
forcedComboMode: .skill
|
||||
),
|
||||
FunctionalButtonOption(
|
||||
localizationKey: "=dummyPad",
|
||||
cmd: "DUMMYPAD",
|
||||
tip: LocalizationHelper.localizedString(forKey: "dummyPadTip"),
|
||||
allowsKeyboardCombination: false,
|
||||
allowsGamepadCombination: false,
|
||||
allowsSkillCombo: false,
|
||||
allowsShortcutCombo: false,
|
||||
forcedComboMode: .skill
|
||||
forcedComboMode: nil
|
||||
),
|
||||
]
|
||||
|
||||
@@ -3739,6 +3749,8 @@ struct FunctionalCollectionButton: View {
|
||||
UIDevice.current.userInterfaceIdiom == .phone ? 8 : 12
|
||||
}
|
||||
|
||||
private let cornerRadius: CGFloat = PublicUtils.isIPhone ? 16 : 24
|
||||
|
||||
var body: some View {
|
||||
Button(action: action) {
|
||||
Text(LocalizationHelper.localizedString(forKey: item.localizationKey))
|
||||
@@ -3757,7 +3769,7 @@ struct FunctionalCollectionButton: View {
|
||||
}
|
||||
|
||||
private var backgroundFill: some View {
|
||||
RoundedRectangle(cornerRadius: 16, style: .continuous)
|
||||
RoundedRectangle(cornerRadius: cornerRadius, style: .continuous)
|
||||
.fill(
|
||||
LinearGradient(
|
||||
gradient: Gradient(colors: isSelected
|
||||
@@ -3777,7 +3789,7 @@ struct FunctionalCollectionButton: View {
|
||||
}
|
||||
|
||||
private var borderOverlay: some View {
|
||||
RoundedRectangle(cornerRadius: 16, style: .continuous)
|
||||
RoundedRectangle(cornerRadius: cornerRadius, style: .continuous)
|
||||
.stroke(
|
||||
isSelected ? Color.orange.opacity(0.75) : Color.white.opacity(0.76),
|
||||
lineWidth: 1.4
|
||||
|
||||
Reference in New Issue
Block a user