aboutsummaryrefslogtreecommitdiff
path: root/Hotline/Application.swift
blob: fdada400686d851d82379e90fdac0814d210693b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
import SwiftUI
import SwiftData
import UniformTypeIdentifiers

@main
struct Application: App {
  #if os(iOS)
  private var model = Hotline(trackerClient: HotlineTrackerClient(), client: HotlineClient())
  #endif
  
  #if os(macOS)
  @Environment(\.openWindow) private var openWindow
  #endif
  
  @State private var preferences = Prefs()
  @State private var soundEffects = SoundEffectPlayer()
  
  @FocusedValue(\.activeHotlineModel) private var activeHotline: Hotline?
  @FocusedValue(\.activeServerState) private var activeServerState: ServerState?
  
  var body: some Scene {
    #if os(iOS)
    WindowGroup {
      TrackerView()
        .environment(model)
    }
    #elseif os(macOS)
    // MARK: Tracker Window
    Window("Servers", id: "servers") {
      TrackerView()
        .frame(minWidth: 250, minHeight: 250)
    }
    .keyboardShortcut(.init(.init("R"), modifiers: .command))
    .defaultSize(width: 700, height: 550)
    .defaultPosition(.center)
        
    // MARK: Server Window
    WindowGroup(id: "server", for: Server.self) { server in
      ServerView(server: server)
        .frame(minWidth: 400, minHeight: 300)
        .environment(preferences)
        .environment(soundEffects)
    } defaultValue: {
      Server(name: nil, description: nil, address: "")
    }
    .defaultSize(width: 750, height: 700)
    .defaultPosition(.center)
    .commands {
      CommandGroup(replacing: CommandGroupPlacement.newItem) {
        Button("Connect to Server...") {
          openWindow(id: "server")
        }
        .keyboardShortcut(.init("K"), modifiers: .command)
      }
      CommandMenu("Server") {
        Button("Disconnect") {
          activeHotline?.disconnect()
        }
        .disabled(activeHotline?.status == .disconnected)
        Divider()
        Button("Broadcast Message...") {
          // TODO: Implement broadcast message when user is allowed.
        }
        .disabled(true)
        .keyboardShortcut(.init("B"), modifiers: .command)
        Divider()
        Button("Show Chat") {
          activeServerState?.selection = .chat
        }
        .disabled(activeHotline?.status != .loggedIn)
        .keyboardShortcut(.init("1"), modifiers: .command)
        Button("Show News") {
          activeServerState?.selection = .news
        }
        .disabled(activeHotline?.status != .loggedIn)
        .keyboardShortcut(.init("2"), modifiers: .command)
        Button("Show Message Board") {
          activeServerState?.selection = .board
        }
        .disabled(activeHotline?.status != .loggedIn)
        .keyboardShortcut(.init("3"), modifiers: .command)
        Button("Show Files") {
          activeServerState?.selection = .files
        }
        .disabled(activeHotline?.status != .loggedIn)
        .keyboardShortcut(.init("4"), modifiers: .command)
      }
    }
    
    // MARK: Settings Window
    Settings {
      SettingsView()
        .environment(preferences)
    }
    
    // MARK: News Editor Window
//    WindowGroup(id: "news-editor", for: NewsArticle.self) { $article in
//      NewsEditorView(article: $article)
//    }
//    .windowResizability(.contentSize)
//    .windowStyle(.titleBar)
//    .windowToolbarStyle(.unifiedCompact(showsTitle: true))
//    .defaultSize(width: 450, height: 550)
//    .defaultPosition(.center)
    
    // MARK: Image Preview Window
    WindowGroup(id: "preview-image", for: PreviewFileInfo.self) { $info in
      FilePreviewImageView(info: $info)
    }
    .windowResizability(.contentSize)
    .windowStyle(.titleBar)
    .windowToolbarStyle(.unifiedCompact(showsTitle: true))
    .defaultSize(width: 350, height: 150)
    .defaultPosition(.center)
    
    // MARK: Text Preview Window
    WindowGroup(id: "preview-text", for: PreviewFileInfo.self) { $info in
      FilePreviewTextView(info: $info)
    }
    .windowResizability(.automatic)
    .windowStyle(.titleBar)
    .windowToolbarStyle(.unifiedCompact(showsTitle: true))
    .defaultSize(width: 450, height: 550)
    .defaultPosition(.center)

    #endif
  }
}