Add unlock complication, improve info display
This commit is contained in:
@ -0,0 +1,25 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "watch",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "watch",
|
||||
"scale" : "2x",
|
||||
"screen-width" : "<=145"
|
||||
},
|
||||
{
|
||||
"idiom" : "watch",
|
||||
"scale" : "2x",
|
||||
"screen-width" : ">183"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
},
|
||||
"properties" : {
|
||||
"auto-scaling" : "auto"
|
||||
}
|
||||
}
|
@ -0,0 +1,53 @@
|
||||
{
|
||||
"assets" : [
|
||||
{
|
||||
"filename" : "Circular.imageset",
|
||||
"idiom" : "watch",
|
||||
"role" : "circular"
|
||||
},
|
||||
{
|
||||
"filename" : "Extra Large.imageset",
|
||||
"idiom" : "watch",
|
||||
"role" : "extra-large"
|
||||
},
|
||||
{
|
||||
"filename" : "Graphic Bezel.imageset",
|
||||
"idiom" : "watch",
|
||||
"role" : "graphic-bezel"
|
||||
},
|
||||
{
|
||||
"filename" : "Graphic Circular.imageset",
|
||||
"idiom" : "watch",
|
||||
"role" : "graphic-circular"
|
||||
},
|
||||
{
|
||||
"filename" : "Graphic Corner.imageset",
|
||||
"idiom" : "watch",
|
||||
"role" : "graphic-corner"
|
||||
},
|
||||
{
|
||||
"filename" : "Graphic Extra Large.imageset",
|
||||
"idiom" : "watch",
|
||||
"role" : "graphic-extra-large"
|
||||
},
|
||||
{
|
||||
"filename" : "Graphic Large Rectangular.imageset",
|
||||
"idiom" : "watch",
|
||||
"role" : "graphic-large-rectangular"
|
||||
},
|
||||
{
|
||||
"filename" : "Modular.imageset",
|
||||
"idiom" : "watch",
|
||||
"role" : "modular"
|
||||
},
|
||||
{
|
||||
"filename" : "Utilitarian.imageset",
|
||||
"idiom" : "watch",
|
||||
"role" : "utilitarian"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
@ -0,0 +1,25 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "watch",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "watch",
|
||||
"scale" : "2x",
|
||||
"screen-width" : "<=145"
|
||||
},
|
||||
{
|
||||
"idiom" : "watch",
|
||||
"scale" : "2x",
|
||||
"screen-width" : ">183"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
},
|
||||
"properties" : {
|
||||
"auto-scaling" : "auto"
|
||||
}
|
||||
}
|
@ -0,0 +1,20 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "watch",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "watch",
|
||||
"scale" : "2x",
|
||||
"screen-width" : ">183"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
},
|
||||
"properties" : {
|
||||
"auto-scaling" : "auto"
|
||||
}
|
||||
}
|
@ -0,0 +1,20 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "watch",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "watch",
|
||||
"scale" : "2x",
|
||||
"screen-width" : ">183"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
},
|
||||
"properties" : {
|
||||
"auto-scaling" : "auto"
|
||||
}
|
||||
}
|
@ -0,0 +1,20 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "watch",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "watch",
|
||||
"scale" : "2x",
|
||||
"screen-width" : ">183"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
},
|
||||
"properties" : {
|
||||
"auto-scaling" : "auto"
|
||||
}
|
||||
}
|
@ -0,0 +1,25 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "watch",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "watch",
|
||||
"scale" : "2x",
|
||||
"screen-width" : "<=145"
|
||||
},
|
||||
{
|
||||
"idiom" : "watch",
|
||||
"scale" : "2x",
|
||||
"screen-width" : ">183"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
},
|
||||
"properties" : {
|
||||
"auto-scaling" : "auto"
|
||||
}
|
||||
}
|
@ -0,0 +1,20 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "watch",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "watch",
|
||||
"scale" : "2x",
|
||||
"screen-width" : ">183"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
},
|
||||
"properties" : {
|
||||
"auto-scaling" : "auto"
|
||||
}
|
||||
}
|
@ -0,0 +1,25 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "watch",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "watch",
|
||||
"scale" : "2x",
|
||||
"screen-width" : "<=145"
|
||||
},
|
||||
{
|
||||
"idiom" : "watch",
|
||||
"scale" : "2x",
|
||||
"screen-width" : ">183"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
},
|
||||
"properties" : {
|
||||
"auto-scaling" : "auto"
|
||||
}
|
||||
}
|
@ -0,0 +1,25 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "watch",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "watch",
|
||||
"scale" : "2x",
|
||||
"screen-width" : "<=145"
|
||||
},
|
||||
{
|
||||
"idiom" : "watch",
|
||||
"scale" : "2x",
|
||||
"screen-width" : ">183"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
},
|
||||
"properties" : {
|
||||
"auto-scaling" : "auto"
|
||||
}
|
||||
}
|
10
Sesame-Watch Watch App/ComplicationController.swift
Normal file
10
Sesame-Watch Watch App/ComplicationController.swift
Normal file
@ -0,0 +1,10 @@
|
||||
import Foundation
|
||||
import ClockKit
|
||||
|
||||
|
||||
class ComplicationController: NSObject, CLKComplicationDataSource {
|
||||
|
||||
func getCurrentTimelineEntry(for complication: CLKComplication, withHandler handler: @escaping (CLKComplicationTimelineEntry?) -> Void) {
|
||||
// TODO: Finish implementing this required method.
|
||||
}
|
||||
}
|
@ -3,6 +3,9 @@ import SFSafeSymbols
|
||||
import CryptoKit
|
||||
|
||||
struct ContentView: View {
|
||||
|
||||
@Binding
|
||||
var didLaunchFromComplication: Bool
|
||||
|
||||
@AppStorage("server")
|
||||
var serverPath: String = "https://christophhagen.de/sesame/"
|
||||
@ -27,6 +30,9 @@ struct ContentView: View {
|
||||
|
||||
@State
|
||||
var state: ClientState = .noKeyAvailable
|
||||
|
||||
@State
|
||||
var stateResetTimer: Timer?
|
||||
|
||||
let server = Client()
|
||||
|
||||
@ -53,18 +59,31 @@ struct ContentView: View {
|
||||
.padding()
|
||||
.onTapGesture(perform: mainButtonPressed)
|
||||
.disabled(!state.allowsAction)
|
||||
Text(state.actionText)
|
||||
.font(.subheadline)
|
||||
if state == .waitingForResponse {
|
||||
ProgressView()
|
||||
.progressViewStyle(CircularProgressViewStyle())
|
||||
.frame(width: 20, height: 20)
|
||||
} else {
|
||||
Text(state.actionText)
|
||||
.font(.subheadline)
|
||||
}
|
||||
}
|
||||
Spacer()
|
||||
}
|
||||
.background(state.color)
|
||||
.animation(.easeInOut, value: state.color)
|
||||
.onAppear {
|
||||
if keyManager.hasAllKeys, state == .noKeyAvailable {
|
||||
if state == .noKeyAvailable, keyManager.hasAllKeys {
|
||||
state = .ready
|
||||
}
|
||||
}
|
||||
.onChange(of: didLaunchFromComplication) { launched in
|
||||
guard launched else {
|
||||
return
|
||||
}
|
||||
didLaunchFromComplication = false
|
||||
mainButtonPressed()
|
||||
}
|
||||
}
|
||||
|
||||
func mainButtonPressed() {
|
||||
@ -83,13 +102,14 @@ struct ContentView: View {
|
||||
device: deviceId)
|
||||
let message = content.authenticate(using: key)
|
||||
let historyItem = HistoryItem(sent: message.content, date: sentTime, local: useLocalConnection)
|
||||
preventStateReset()
|
||||
state = .waitingForResponse
|
||||
print("Sending message \(count)")
|
||||
Task {
|
||||
let (newState, responseMessage) = await send(message, authToken: token)
|
||||
let receivedTime = Date.now
|
||||
//responseTime = receivedTime
|
||||
state = newState
|
||||
scheduleStateReset()
|
||||
let finishedItem = historyItem.didReceive(response: newState, date: receivedTime, message: responseMessage?.content)
|
||||
guard let key = keyManager.get(.deviceKey) else {
|
||||
save(historyItem: finishedItem.notAuthenticated())
|
||||
@ -108,6 +128,25 @@ struct ContentView: View {
|
||||
save(historyItem: finishedItem)
|
||||
}
|
||||
}
|
||||
|
||||
private func preventStateReset() {
|
||||
stateResetTimer?.invalidate()
|
||||
stateResetTimer = nil
|
||||
}
|
||||
|
||||
private func scheduleStateReset() {
|
||||
stateResetTimer?.invalidate()
|
||||
stateResetTimer = Timer.scheduledTimer(withTimeInterval: 8.0, repeats: false) { _ in
|
||||
DispatchQueue.main.async {
|
||||
resetState()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private func resetState() {
|
||||
state = keyManager.hasAllKeys ? .ready : .noKeyAvailable
|
||||
preventStateReset()
|
||||
}
|
||||
|
||||
private func send(_ message: Message, authToken: Data) async -> (state: ClientState, response: Message?) {
|
||||
if useLocalConnection {
|
||||
@ -128,7 +167,7 @@ struct ContentView: View {
|
||||
|
||||
struct ContentView_Previews: PreviewProvider {
|
||||
static var previews: some View {
|
||||
ContentView()
|
||||
ContentView(didLaunchFromComplication: .constant(false))
|
||||
.environmentObject(KeyManagement())
|
||||
}
|
||||
}
|
||||
|
@ -4,17 +4,30 @@ import SwiftUI
|
||||
struct Sesame_Watch_Watch_AppApp: App {
|
||||
|
||||
let keyManagement = KeyManagement()
|
||||
|
||||
@State
|
||||
var selected: Int = 0
|
||||
|
||||
@State
|
||||
var didLaunchFromComplication = false
|
||||
|
||||
var body: some Scene {
|
||||
WindowGroup {
|
||||
TabView {
|
||||
ContentView()
|
||||
TabView(selection: $selected) {
|
||||
ContentView(didLaunchFromComplication: $didLaunchFromComplication)
|
||||
.environmentObject(keyManagement)
|
||||
.tag(1)
|
||||
SettingsView()
|
||||
.environmentObject(keyManagement)
|
||||
.tag(2)
|
||||
HistoryView(history: HistoryManager())
|
||||
.tag(3)
|
||||
}
|
||||
.tabViewStyle(PageTabViewStyle())
|
||||
.onOpenURL { url in
|
||||
selected = 0
|
||||
didLaunchFromComplication = true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user