mirror of
https://github.com/keymanapp/keyman.git
synced 2026-09-26 17:47:40 +00:00
feat(mac): added tabview and webview
This commit is contained in:
parent
5c59da838b
commit
2b2fc15da3
4 changed files with 102 additions and 35 deletions
34
mac/Config/Config/HelpView.swift
Normal file
34
mac/Config/Config/HelpView.swift
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
/*
|
||||
* Keyman is copyright (C) SIL Global. MIT License.
|
||||
*
|
||||
* Created by Gabriel Schantz on 2026-08-03
|
||||
*
|
||||
* Webview used to show help for Keyman keyboards
|
||||
*/
|
||||
import Foundation
|
||||
|
||||
import SwiftUI
|
||||
import WebKit
|
||||
import KeymanSettings
|
||||
|
||||
public struct HelpView: NSViewRepresentable {
|
||||
@EnvironmentObject var settings: SettingsContainer
|
||||
|
||||
let helpFileURL: URL
|
||||
|
||||
// create the AppKit view instance
|
||||
public func makeNSView(context: Context) -> WKWebView {
|
||||
let webView = WKWebView()
|
||||
return webView
|
||||
}
|
||||
|
||||
// update the view when SwiftUI state changes
|
||||
public func updateNSView(_ nsView: WKWebView, context: Context) {
|
||||
let request = URLRequest(url: helpFileURL)
|
||||
|
||||
// only load the request if it's not already loading/loaded to prevent infinite loops
|
||||
if nsView.url != helpFileURL {
|
||||
nsView.load(request)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -4,8 +4,7 @@
|
|||
* Created by Gabriel Schantz on 2026-06-29
|
||||
*
|
||||
* Main view used for configuring Keyman
|
||||
* FEAT/MAC/CONFIG-WINDOW TODO: Finish writing file summary
|
||||
* FEAT/MAC/CONFIG-WINDOW TODO: Set width and height for window
|
||||
* FEAT/MAC/CONFIG-WINDOW TODO: Set default width and height for window
|
||||
*/
|
||||
|
||||
import SwiftUI
|
||||
|
|
@ -17,43 +16,68 @@ struct MainConfigView: View {
|
|||
// visibilty state for the add package sheet
|
||||
@State private var isShowingSheet = false
|
||||
// used to identify the expanded KeymanPackage id
|
||||
// both single and multi package views share the same state variable so only single disclosure group is expanded at once
|
||||
// both single and multi package views share the same state variable so only a single disclosure group is expanded at once
|
||||
@State private var expandedPackageID: UUID? = nil
|
||||
@State private var selectedTab = 0
|
||||
@State private var packageSelectedForHelpUrl: URL? = nil
|
||||
|
||||
/**
|
||||
* Assigns packageSelectedForHelpUrl the url argument and changes the selected tab to the help tab
|
||||
*/
|
||||
public func showHelpTab(for url: URL) {
|
||||
packageSelectedForHelpUrl = url
|
||||
selectedTab = 1
|
||||
}
|
||||
|
||||
var body: some View {
|
||||
VStack {
|
||||
// the add keyboard button
|
||||
LabelButtonView(
|
||||
action: { isShowingSheet = true },
|
||||
label: "Add Keyboard",
|
||||
systemImage: "plus",
|
||||
font: .title2
|
||||
)
|
||||
.clipShape(.capsule)
|
||||
.padding([.top, .leading, .trailing])
|
||||
// binds the visibility state to the sheet builder
|
||||
.sheet(isPresented: $isShowingSheet) {
|
||||
InstallKeyboardView()
|
||||
.frame(width: 960, height: 390)
|
||||
// FEAT/MAC/CONFIG-WINDOW TODO: Make width and height percentages
|
||||
}
|
||||
ScrollView {
|
||||
VStack {
|
||||
TabView (selection: $selectedTab) {
|
||||
VStack {
|
||||
// the add keyboard button
|
||||
LabelButtonView(
|
||||
action: { isShowingSheet = true },
|
||||
label: "Add Keyboard",
|
||||
systemImage: "plus",
|
||||
font: .title2
|
||||
)
|
||||
.clipShape(.capsule)
|
||||
.padding([.top, .leading, .trailing])
|
||||
// binds the visibility state to the sheet builder
|
||||
.sheet(isPresented: $isShowingSheet) {
|
||||
InstallKeyboardView()
|
||||
.frame(width: 960, height: 390)
|
||||
// FEAT/MAC/CONFIG-WINDOW TODO: Make width and height percentages
|
||||
}
|
||||
|
||||
Form {
|
||||
// the view for single keyboard packages
|
||||
PackageRowView(packages: settings.singleKeyboardPackages, isSingleKeyboardPackage: true, expandedPackageID: $expandedPackageID)
|
||||
PackageRowView(packages: settings.singleKeyboardPackages, isSingleKeyboardPackage: true, expandedPackageID: $expandedPackageID, showHelpTab: { url in
|
||||
showHelpTab(for: url)})
|
||||
|
||||
// the view for multi keyboard packages
|
||||
PackageRowView(packages: settings.multiKeyboardPackages, isSingleKeyboardPackage: false, expandedPackageID: $expandedPackageID)
|
||||
PackageRowView(packages: settings.multiKeyboardPackages, isSingleKeyboardPackage: false, expandedPackageID: $expandedPackageID, showHelpTab: { url in
|
||||
showHelpTab(for: url) })
|
||||
}
|
||||
.padding()
|
||||
.background(.quinary)
|
||||
.clipShape(RoundedRectangle(cornerRadius: 12, style: .continuous))
|
||||
.formStyle(.grouped)
|
||||
|
||||
// the Spacer pushes the contents of the VStack to the top of the VStack
|
||||
Spacer()
|
||||
}
|
||||
.padding([.leading, .trailing, .bottom])
|
||||
.tabItem { Text("Keyboards") }
|
||||
.tag(0)
|
||||
|
||||
if let url = packageSelectedForHelpUrl {
|
||||
HelpView(helpFileURL: url)
|
||||
.padding()
|
||||
.tabItem { Text("Help") }
|
||||
.tag(1)
|
||||
} else {
|
||||
Text("Help not available.")
|
||||
.font(.title)
|
||||
.tabItem { Text("Help") }
|
||||
.tag(1)
|
||||
}
|
||||
}
|
||||
.padding([.leading, .trailing, .bottom])
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -39,6 +39,7 @@ public struct PackageInfoView: View {
|
|||
VStack (alignment: .leading) {
|
||||
// the text-based package properties presented in a grid
|
||||
Grid(horizontalSpacing: 10, verticalSpacing: 5) {
|
||||
|
||||
// the package version
|
||||
GridRow {
|
||||
Text("Package Version:").bold()
|
||||
|
|
|
|||
|
|
@ -20,14 +20,18 @@ public struct PackageRowView: View {
|
|||
|
||||
// settings.singleKeyboardPackages or settings.multiKeyboardPackages
|
||||
let packages: [KeymanPackage]
|
||||
// a boolean for weather or not a package contains multiple keyboards
|
||||
let isSingleKeyboardPackage: Bool
|
||||
// binded to the shared state variable in the parent view
|
||||
@Binding var expandedPackageID: UUID?
|
||||
// closure passed from the parent view
|
||||
let showHelpTab: (URL) -> Void
|
||||
|
||||
init(packages: [KeymanPackage], isSingleKeyboardPackage: Bool, expandedPackageID: Binding<UUID?>) {
|
||||
init(packages: [KeymanPackage], isSingleKeyboardPackage: Bool, expandedPackageID: Binding<UUID?>, showHelpTab: @escaping (URL) -> Void) {
|
||||
self.packages = packages
|
||||
self.isSingleKeyboardPackage = isSingleKeyboardPackage
|
||||
self._expandedPackageID = expandedPackageID
|
||||
self.showHelpTab = showHelpTab
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -57,6 +61,16 @@ public struct PackageRowView: View {
|
|||
Text(isSingleKeyboardPackage ? keyboard.name: package.packageName)
|
||||
.font(.title)
|
||||
|
||||
// see keyboard help button
|
||||
if let url = package.helpFileUrl {
|
||||
IconButtonView(
|
||||
action: { showHelpTab(url) },
|
||||
systemImage: "questionmark.circle",
|
||||
font: .title2,
|
||||
helpText: "Show keyboard help"
|
||||
)
|
||||
}
|
||||
|
||||
// the Spacer pushes the contents of the HStack to the either edge
|
||||
Spacer()
|
||||
|
||||
|
|
@ -69,13 +83,7 @@ public struct PackageRowView: View {
|
|||
.gridColumnAlignment(.leading)
|
||||
}
|
||||
|
||||
// see keyboard help button
|
||||
IconButtonView(
|
||||
action: { print("Show keyboard help") },
|
||||
systemImage: "questionmark.circle",
|
||||
font: .title2,
|
||||
helpText: "Show keyboard help"
|
||||
)
|
||||
|
||||
}
|
||||
|
||||
// if the package contains multiple keyboards shows an HStack with the keyboard name and toggle button for each keyboard in the package
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue