Compare commits
8 Commits
29bd87f287
...
70bbbc5583
Author | SHA1 | Date |
---|---|---|
Shadowfacts | 70bbbc5583 | |
Shadowfacts | 70555eb317 | |
Shadowfacts | 6f2b98ac31 | |
Shadowfacts | f59c43afa7 | |
Shadowfacts | 80fcfd3b91 | |
Shadowfacts | ab34d537d8 | |
Shadowfacts | 2d05e318ff | |
Shadowfacts | bd48fc8dbb |
|
@ -0,0 +1,18 @@
|
|||
//
|
||||
// BrowserCore.h
|
||||
// BrowserCore
|
||||
//
|
||||
// Created by Shadowfacts on 7/15/20.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
//! Project version number for BrowserCore.
|
||||
FOUNDATION_EXPORT double BrowserCoreVersionNumber;
|
||||
|
||||
//! Project version string for BrowserCore.
|
||||
FOUNDATION_EXPORT const unsigned char BrowserCoreVersionString[];
|
||||
|
||||
// In this header, you should import all the public headers of your framework using statements like #import <BrowserCore/PublicHeader.h>
|
||||
|
||||
|
|
@ -0,0 +1,96 @@
|
|||
//
|
||||
// ContentView.swift
|
||||
// Gemini
|
||||
//
|
||||
// Created by Shadowfacts on 7/12/20.
|
||||
//
|
||||
|
||||
import SwiftUI
|
||||
import GeminiFormat
|
||||
import GeminiRenderer
|
||||
import GeminiProtocol
|
||||
|
||||
public struct BrowserView: View {
|
||||
let navigator: NavigationManager
|
||||
@State var task: GeminiDataTask?
|
||||
@State var state: ViewState = .loading
|
||||
|
||||
public init(navigator: NavigationManager) {
|
||||
self.navigator = navigator
|
||||
}
|
||||
|
||||
public var body: some View {
|
||||
mainView
|
||||
.onReceive(navigator.$currentURL, perform: self.urlChanged)
|
||||
}
|
||||
|
||||
@ViewBuilder
|
||||
private var mainView: some View {
|
||||
switch state {
|
||||
case .loading:
|
||||
loadingView
|
||||
.onAppear(perform: self.loadDocument)
|
||||
case let .error(message):
|
||||
VStack {
|
||||
Text("An error occurred")
|
||||
.font(.headline)
|
||||
Text(message)
|
||||
}
|
||||
case let .document(doc):
|
||||
DocumentView(document: doc, changeURL: navigator.changeURL)
|
||||
}
|
||||
}
|
||||
|
||||
@ViewBuilder
|
||||
private var loadingView: some View {
|
||||
if #available(macOS 10.16, iOS 14.0, *) {
|
||||
ProgressView("Loading...")
|
||||
} else {
|
||||
Text("Loading...")
|
||||
}
|
||||
}
|
||||
|
||||
private func loadDocument() {
|
||||
let url = navigator.currentURL
|
||||
task = try! GeminiDataTask(url: url, completion: { (response) in
|
||||
self.task = nil
|
||||
switch response {
|
||||
case let .failure(error):
|
||||
state = .error(error.localizedDescription)
|
||||
case let .success(response):
|
||||
if response.status.isRedirect {
|
||||
if let redirect = URL(string: response.meta) {
|
||||
navigator.changeURL(redirect)
|
||||
loadDocument()
|
||||
} else {
|
||||
state = .error("Invalid redirect URL: '\(response.meta)'")
|
||||
}
|
||||
} else if response.status.isSuccess,
|
||||
let text = response.bodyText {
|
||||
state = .document(GeminiParser.parse(text: text, baseURL: url))
|
||||
} else {
|
||||
state = .error("Unknown error: \(response.header)")
|
||||
}
|
||||
}
|
||||
})
|
||||
task!.resume()
|
||||
}
|
||||
|
||||
private func urlChanged(_ newValue: URL) {
|
||||
state = .loading
|
||||
}
|
||||
}
|
||||
|
||||
extension BrowserView {
|
||||
enum ViewState {
|
||||
case loading
|
||||
case document(Document)
|
||||
case error(String)
|
||||
}
|
||||
}
|
||||
|
||||
struct ContentView_Previews: PreviewProvider {
|
||||
static var previews: some View {
|
||||
BrowserView(navigator: NavigationManager(url: URL(string: "gemini://localhost/overview.gmi")!))
|
||||
}
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>CFBundleDevelopmentRegion</key>
|
||||
<string>$(DEVELOPMENT_LANGUAGE)</string>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>$(EXECUTABLE_NAME)</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
<string>6.0</string>
|
||||
<key>CFBundleName</key>
|
||||
<string>$(PRODUCT_NAME)</string>
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>$(PRODUCT_BUNDLE_PACKAGE_TYPE)</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>1.0</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>$(CURRENT_PROJECT_VERSION)</string>
|
||||
</dict>
|
||||
</plist>
|
|
@ -0,0 +1,46 @@
|
|||
//
|
||||
// NavigationManager.swift
|
||||
// Gemini
|
||||
//
|
||||
// Created by Shadowfacts on 7/14/20.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
public class NavigationManager: NSObject, ObservableObject {
|
||||
|
||||
@Published public var currentURL: URL
|
||||
@Published public var backStack = [URL]()
|
||||
@Published public var forwardStack = [URL]()
|
||||
|
||||
public init(url: URL) {
|
||||
self.currentURL = url
|
||||
}
|
||||
|
||||
public func changeURL(_ url: URL) {
|
||||
backStack.append(currentURL)
|
||||
currentURL = cannonicalizeURL(url)
|
||||
forwardStack = []
|
||||
}
|
||||
|
||||
private func cannonicalizeURL(_ url: URL) -> URL {
|
||||
var components = URLComponents(url: url, resolvingAgainstBaseURL: false)!
|
||||
if components.scheme == "gemini" && components.port == 1965 {
|
||||
components.port = nil
|
||||
}
|
||||
return components.url!
|
||||
}
|
||||
|
||||
@objc public func back() {
|
||||
guard !backStack.isEmpty else { return }
|
||||
forwardStack.insert(currentURL, at: 0)
|
||||
currentURL = backStack.removeLast()
|
||||
}
|
||||
|
||||
@objc public func forward() {
|
||||
guard !forwardStack.isEmpty else { return }
|
||||
backStack.append(currentURL)
|
||||
currentURL = forwardStack.removeFirst()
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,33 @@
|
|||
//
|
||||
// BrowserCoreTests.swift
|
||||
// BrowserCoreTests
|
||||
//
|
||||
// Created by Shadowfacts on 7/15/20.
|
||||
//
|
||||
|
||||
import XCTest
|
||||
@testable import BrowserCore
|
||||
|
||||
class BrowserCoreTests: XCTestCase {
|
||||
|
||||
override func setUpWithError() throws {
|
||||
// Put setup code here. This method is called before the invocation of each test method in the class.
|
||||
}
|
||||
|
||||
override func tearDownWithError() throws {
|
||||
// Put teardown code here. This method is called after the invocation of each test method in the class.
|
||||
}
|
||||
|
||||
func testExample() throws {
|
||||
// This is an example of a functional test case.
|
||||
// Use XCTAssert and related functions to verify your tests produce the correct results.
|
||||
}
|
||||
|
||||
func testPerformanceExample() throws {
|
||||
// This is an example of a performance test case.
|
||||
self.measure {
|
||||
// Put the code you want to measure the time of here.
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>CFBundleDevelopmentRegion</key>
|
||||
<string>$(DEVELOPMENT_LANGUAGE)</string>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>$(EXECUTABLE_NAME)</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
<string>6.0</string>
|
||||
<key>CFBundleName</key>
|
||||
<string>$(PRODUCT_NAME)</string>
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>$(PRODUCT_BUNDLE_PACKAGE_TYPE)</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>1.0</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>1</string>
|
||||
</dict>
|
||||
</plist>
|
|
@ -0,0 +1,36 @@
|
|||
//
|
||||
// AppDelegate.swift
|
||||
// Gemini-iOS
|
||||
//
|
||||
// Created by Shadowfacts on 7/15/20.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
|
||||
@UIApplicationMain
|
||||
class AppDelegate: UIResponder, UIApplicationDelegate {
|
||||
|
||||
|
||||
|
||||
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
|
||||
// Override point for customization after application launch.
|
||||
return true
|
||||
}
|
||||
|
||||
// MARK: UISceneSession Lifecycle
|
||||
|
||||
func application(_ application: UIApplication, configurationForConnecting connectingSceneSession: UISceneSession, options: UIScene.ConnectionOptions) -> UISceneConfiguration {
|
||||
// Called when a new scene session is being created.
|
||||
// Use this method to select a configuration to create the new scene with.
|
||||
return UISceneConfiguration(name: "Default Configuration", sessionRole: connectingSceneSession.role)
|
||||
}
|
||||
|
||||
func application(_ application: UIApplication, didDiscardSceneSessions sceneSessions: Set<UISceneSession>) {
|
||||
// Called when the user discards a scene session.
|
||||
// If any sessions were discarded while the application was not running, this will be called shortly after application:didFinishLaunchingWithOptions.
|
||||
// Use this method to release any resources that were specific to the discarded scenes, as they will not return.
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
{
|
||||
"colors" : [
|
||||
{
|
||||
"idiom" : "universal"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
|
@ -0,0 +1,98 @@
|
|||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "iphone",
|
||||
"scale" : "2x",
|
||||
"size" : "20x20"
|
||||
},
|
||||
{
|
||||
"idiom" : "iphone",
|
||||
"scale" : "3x",
|
||||
"size" : "20x20"
|
||||
},
|
||||
{
|
||||
"idiom" : "iphone",
|
||||
"scale" : "2x",
|
||||
"size" : "29x29"
|
||||
},
|
||||
{
|
||||
"idiom" : "iphone",
|
||||
"scale" : "3x",
|
||||
"size" : "29x29"
|
||||
},
|
||||
{
|
||||
"idiom" : "iphone",
|
||||
"scale" : "2x",
|
||||
"size" : "40x40"
|
||||
},
|
||||
{
|
||||
"idiom" : "iphone",
|
||||
"scale" : "3x",
|
||||
"size" : "40x40"
|
||||
},
|
||||
{
|
||||
"idiom" : "iphone",
|
||||
"scale" : "2x",
|
||||
"size" : "60x60"
|
||||
},
|
||||
{
|
||||
"idiom" : "iphone",
|
||||
"scale" : "3x",
|
||||
"size" : "60x60"
|
||||
},
|
||||
{
|
||||
"idiom" : "ipad",
|
||||
"scale" : "1x",
|
||||
"size" : "20x20"
|
||||
},
|
||||
{
|
||||
"idiom" : "ipad",
|
||||
"scale" : "2x",
|
||||
"size" : "20x20"
|
||||
},
|
||||
{
|
||||
"idiom" : "ipad",
|
||||
"scale" : "1x",
|
||||
"size" : "29x29"
|
||||
},
|
||||
{
|
||||
"idiom" : "ipad",
|
||||
"scale" : "2x",
|
||||
"size" : "29x29"
|
||||
},
|
||||
{
|
||||
"idiom" : "ipad",
|
||||
"scale" : "1x",
|
||||
"size" : "40x40"
|
||||
},
|
||||
{
|
||||
"idiom" : "ipad",
|
||||
"scale" : "2x",
|
||||
"size" : "40x40"
|
||||
},
|
||||
{
|
||||
"idiom" : "ipad",
|
||||
"scale" : "1x",
|
||||
"size" : "76x76"
|
||||
},
|
||||
{
|
||||
"idiom" : "ipad",
|
||||
"scale" : "2x",
|
||||
"size" : "76x76"
|
||||
},
|
||||
{
|
||||
"idiom" : "ipad",
|
||||
"scale" : "2x",
|
||||
"size" : "83.5x83.5"
|
||||
},
|
||||
{
|
||||
"idiom" : "ios-marketing",
|
||||
"scale" : "1x",
|
||||
"size" : "1024x1024"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
|
@ -0,0 +1,6 @@
|
|||
{
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
|
@ -0,0 +1,25 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="13122.16" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="01J-lp-oVM">
|
||||
<dependencies>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="13104.12"/>
|
||||
<capability name="Safe area layout guides" minToolsVersion="9.0"/>
|
||||
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
||||
</dependencies>
|
||||
<scenes>
|
||||
<!--View Controller-->
|
||||
<scene sceneID="EHf-IW-A2E">
|
||||
<objects>
|
||||
<viewController id="01J-lp-oVM" sceneMemberID="viewController">
|
||||
<view key="view" contentMode="scaleToFill" id="Ze5-6b-2t3">
|
||||
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<color key="backgroundColor" xcode11CocoaTouchSystemColor="systemBackgroundColor" cocoaTouchSystemColor="whiteColor"/>
|
||||
<viewLayoutGuide key="safeArea" id="6Tk-OE-BBY"/>
|
||||
</view>
|
||||
</viewController>
|
||||
<placeholder placeholderIdentifier="IBFirstResponder" id="iYj-Kq-Ea1" userLabel="First Responder" sceneMemberID="firstResponder"/>
|
||||
</objects>
|
||||
<point key="canvasLocation" x="53" y="375"/>
|
||||
</scene>
|
||||
</scenes>
|
||||
</document>
|
|
@ -0,0 +1,23 @@
|
|||
//
|
||||
// ContentView.swift
|
||||
// Gemini-iOS
|
||||
//
|
||||
// Created by Shadowfacts on 7/15/20.
|
||||
//
|
||||
|
||||
import SwiftUI
|
||||
import BrowserCore
|
||||
|
||||
struct ContentView: View {
|
||||
let navigator: NavigationManager
|
||||
|
||||
var body: some View {
|
||||
BrowserView(navigator: navigator)
|
||||
}
|
||||
}
|
||||
|
||||
struct ContentView_Previews: PreviewProvider {
|
||||
static var previews: some View {
|
||||
ContentView(navigator: NavigationManager(url: URL(string: "gemini://localhost/overview.gmi")!))
|
||||
}
|
||||
}
|
|
@ -0,0 +1,62 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>CFBundleDevelopmentRegion</key>
|
||||
<string>$(DEVELOPMENT_LANGUAGE)</string>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>$(EXECUTABLE_NAME)</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
<string>6.0</string>
|
||||
<key>CFBundleName</key>
|
||||
<string>$(PRODUCT_NAME)</string>
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>$(PRODUCT_BUNDLE_PACKAGE_TYPE)</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>1.0</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>1</string>
|
||||
<key>LSRequiresIPhoneOS</key>
|
||||
<true/>
|
||||
<key>UIApplicationSceneManifest</key>
|
||||
<dict>
|
||||
<key>UIApplicationSupportsMultipleScenes</key>
|
||||
<false/>
|
||||
<key>UISceneConfigurations</key>
|
||||
<dict>
|
||||
<key>UIWindowSceneSessionRoleApplication</key>
|
||||
<array>
|
||||
<dict>
|
||||
<key>UISceneConfigurationName</key>
|
||||
<string>Default Configuration</string>
|
||||
<key>UISceneDelegateClassName</key>
|
||||
<string>$(PRODUCT_MODULE_NAME).SceneDelegate</string>
|
||||
</dict>
|
||||
</array>
|
||||
</dict>
|
||||
</dict>
|
||||
<key>UIApplicationSupportsIndirectInputEvents</key>
|
||||
<true/>
|
||||
<key>UILaunchStoryboardName</key>
|
||||
<string>LaunchScreen</string>
|
||||
<key>UIRequiredDeviceCapabilities</key>
|
||||
<array>
|
||||
<string>armv7</string>
|
||||
</array>
|
||||
<key>UISupportedInterfaceOrientations</key>
|
||||
<array>
|
||||
<string>UIInterfaceOrientationPortrait</string>
|
||||
<string>UIInterfaceOrientationLandscapeLeft</string>
|
||||
<string>UIInterfaceOrientationLandscapeRight</string>
|
||||
</array>
|
||||
<key>UISupportedInterfaceOrientations~ipad</key>
|
||||
<array>
|
||||
<string>UIInterfaceOrientationPortrait</string>
|
||||
<string>UIInterfaceOrientationPortraitUpsideDown</string>
|
||||
<string>UIInterfaceOrientationLandscapeLeft</string>
|
||||
<string>UIInterfaceOrientationLandscapeRight</string>
|
||||
</array>
|
||||
</dict>
|
||||
</plist>
|
|
@ -0,0 +1,6 @@
|
|||
{
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
|
@ -0,0 +1,65 @@
|
|||
//
|
||||
// SceneDelegate.swift
|
||||
// Gemini-iOS
|
||||
//
|
||||
// Created by Shadowfacts on 7/15/20.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
import SwiftUI
|
||||
import BrowserCore
|
||||
|
||||
class SceneDelegate: UIResponder, UIWindowSceneDelegate {
|
||||
|
||||
var window: UIWindow?
|
||||
|
||||
let navigationManager = NavigationManager(url: URL(string: "gemini://gemini.circumlunar.space/")!)
|
||||
|
||||
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
|
||||
// Use this method to optionally configure and attach the UIWindow `window` to the provided UIWindowScene `scene`.
|
||||
// If using a storyboard, the `window` property will automatically be initialized and attached to the scene.
|
||||
// This delegate does not imply the connecting scene or session are new (see `application:configurationForConnectingSceneSession` instead).
|
||||
|
||||
// Create the SwiftUI view that provides the window contents.
|
||||
let contentView = ContentView(navigator: navigationManager)
|
||||
|
||||
// Use a UIHostingController as window root view controller.
|
||||
if let windowScene = scene as? UIWindowScene {
|
||||
let window = UIWindow(windowScene: windowScene)
|
||||
window.rootViewController = UIHostingController(rootView: contentView)
|
||||
self.window = window
|
||||
window.makeKeyAndVisible()
|
||||
}
|
||||
}
|
||||
|
||||
func sceneDidDisconnect(_ scene: UIScene) {
|
||||
// Called as the scene is being released by the system.
|
||||
// This occurs shortly after the scene enters the background, or when its session is discarded.
|
||||
// Release any resources associated with this scene that can be re-created the next time the scene connects.
|
||||
// The scene may re-connect later, as its session was not necessarily discarded (see `application:didDiscardSceneSessions` instead).
|
||||
}
|
||||
|
||||
func sceneDidBecomeActive(_ scene: UIScene) {
|
||||
// Called when the scene has moved from an inactive state to an active state.
|
||||
// Use this method to restart any tasks that were paused (or not yet started) when the scene was inactive.
|
||||
}
|
||||
|
||||
func sceneWillResignActive(_ scene: UIScene) {
|
||||
// Called when the scene will move from an active state to an inactive state.
|
||||
// This may occur due to temporary interruptions (ex. an incoming phone call).
|
||||
}
|
||||
|
||||
func sceneWillEnterForeground(_ scene: UIScene) {
|
||||
// Called as the scene transitions from the background to the foreground.
|
||||
// Use this method to undo the changes made on entering the background.
|
||||
}
|
||||
|
||||
func sceneDidEnterBackground(_ scene: UIScene) {
|
||||
// Called as the scene transitions from the foreground to the background.
|
||||
// Use this method to save data, release shared resources, and store enough scene-specific state information
|
||||
// to restore the scene back to its current state.
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -8,10 +8,8 @@
|
|||
|
||||
/* Begin PBXBuildFile section */
|
||||
D626645F24BBF1C200DF9B88 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = D626645E24BBF1C200DF9B88 /* AppDelegate.swift */; };
|
||||
D626646124BBF1C200DF9B88 /* ContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D626646024BBF1C200DF9B88 /* ContentView.swift */; };
|
||||
D626646324BBF1C300DF9B88 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = D626646224BBF1C300DF9B88 /* Assets.xcassets */; };
|
||||
D626646624BBF1C300DF9B88 /* Preview Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = D626646524BBF1C300DF9B88 /* Preview Assets.xcassets */; };
|
||||
D626646924BBF1C300DF9B88 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = D626646724BBF1C300DF9B88 /* Main.storyboard */; };
|
||||
D626648024BBF22E00DF9B88 /* GeminiProtocol.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D626647724BBF22E00DF9B88 /* GeminiProtocol.framework */; };
|
||||
D626648724BBF22E00DF9B88 /* GeminiProtocolTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D626648624BBF22E00DF9B88 /* GeminiProtocolTests.swift */; };
|
||||
D626648924BBF22E00DF9B88 /* GeminiProtocol.h in Headers */ = {isa = PBXBuildFile; fileRef = D626647924BBF22E00DF9B88 /* GeminiProtocol.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
|
@ -45,7 +43,31 @@
|
|||
D664673A24BD0B8E00B0B741 /* Fonts.swift in Sources */ = {isa = PBXBuildFile; fileRef = D664673924BD0B8E00B0B741 /* Fonts.swift */; };
|
||||
D69F00AC24BE9DD300E37622 /* GeminiDataTask.swift in Sources */ = {isa = PBXBuildFile; fileRef = D69F00AB24BE9DD300E37622 /* GeminiDataTask.swift */; };
|
||||
D69F00AE24BEA29100E37622 /* GeminiResponse.swift in Sources */ = {isa = PBXBuildFile; fileRef = D69F00AD24BEA29100E37622 /* GeminiResponse.swift */; };
|
||||
D69F00B024BEA84D00E37622 /* NavigationManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = D69F00AF24BEA84D00E37622 /* NavigationManager.swift */; };
|
||||
D6E1529824BFAAA400FDF9D3 /* BrowserWindowController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6E1529624BFAAA400FDF9D3 /* BrowserWindowController.swift */; };
|
||||
D6E1529924BFAAA400FDF9D3 /* BrowserWindowController.xib in Resources */ = {isa = PBXBuildFile; fileRef = D6E1529724BFAAA400FDF9D3 /* BrowserWindowController.xib */; };
|
||||
D6E1529B24BFAEC700FDF9D3 /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = D6E1529A24BFAEC700FDF9D3 /* MainMenu.xib */; };
|
||||
D6E152A524BFFDF500FDF9D3 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6E152A424BFFDF500FDF9D3 /* AppDelegate.swift */; };
|
||||
D6E152A724BFFDF500FDF9D3 /* SceneDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6E152A624BFFDF500FDF9D3 /* SceneDelegate.swift */; };
|
||||
D6E152A924BFFDF500FDF9D3 /* ContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6E152A824BFFDF500FDF9D3 /* ContentView.swift */; };
|
||||
D6E152AB24BFFDF600FDF9D3 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = D6E152AA24BFFDF600FDF9D3 /* Assets.xcassets */; };
|
||||
D6E152AE24BFFDF600FDF9D3 /* Preview Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = D6E152AD24BFFDF600FDF9D3 /* Preview Assets.xcassets */; };
|
||||
D6E152B124BFFDF600FDF9D3 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = D6E152AF24BFFDF600FDF9D3 /* LaunchScreen.storyboard */; };
|
||||
D6E152B624BFFE2400FDF9D3 /* GeminiFormat.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D62664A824BBF26A00DF9B88 /* GeminiFormat.framework */; };
|
||||
D6E152B724BFFE2400FDF9D3 /* GeminiFormat.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = D62664A824BBF26A00DF9B88 /* GeminiFormat.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
|
||||
D6E152C324C0004C00FDF9D3 /* GeminiProtocol.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D626647724BBF22E00DF9B88 /* GeminiProtocol.framework */; };
|
||||
D6E152C424C0004C00FDF9D3 /* GeminiProtocol.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = D626647724BBF22E00DF9B88 /* GeminiProtocol.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
|
||||
D6E152C724C0004C00FDF9D3 /* GeminiRenderer.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D62664CE24BC081B00DF9B88 /* GeminiRenderer.framework */; };
|
||||
D6E152C824C0004C00FDF9D3 /* GeminiRenderer.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = D62664CE24BC081B00DF9B88 /* GeminiRenderer.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
|
||||
D6E152D924C0007200FDF9D3 /* BrowserCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D6E152D024C0007200FDF9D3 /* BrowserCore.framework */; };
|
||||
D6E152E024C0007200FDF9D3 /* BrowserCoreTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6E152DF24C0007200FDF9D3 /* BrowserCoreTests.swift */; };
|
||||
D6E152E224C0007200FDF9D3 /* BrowserCore.h in Headers */ = {isa = PBXBuildFile; fileRef = D6E152D224C0007200FDF9D3 /* BrowserCore.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
D6E152E524C0007200FDF9D3 /* BrowserCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D6E152D024C0007200FDF9D3 /* BrowserCore.framework */; };
|
||||
D6E152E624C0007200FDF9D3 /* BrowserCore.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = D6E152D024C0007200FDF9D3 /* BrowserCore.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
|
||||
D6E152ED24C0009300FDF9D3 /* BrowserCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D6E152D024C0007200FDF9D3 /* BrowserCore.framework */; };
|
||||
D6E152EE24C0009300FDF9D3 /* BrowserCore.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = D6E152D024C0007200FDF9D3 /* BrowserCore.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
|
||||
D6E152F124C000A000FDF9D3 /* NavigationManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = D69F00AF24BEA84D00E37622 /* NavigationManager.swift */; };
|
||||
D6E152F224C000CD00FDF9D3 /* BrowserView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D626646024BBF1C200DF9B88 /* BrowserView.swift */; };
|
||||
D6E152F424C000DA00FDF9D3 /* ContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6E152F324C000DA00FDF9D3 /* ContentView.swift */; };
|
||||
/* End PBXBuildFile section */
|
||||
|
||||
/* Begin PBXContainerItemProxy section */
|
||||
|
@ -119,6 +141,55 @@
|
|||
remoteGlobalIDString = D62664A724BBF26A00DF9B88;
|
||||
remoteInfo = GeminiFormat;
|
||||
};
|
||||
D6E152B824BFFE2400FDF9D3 /* PBXContainerItemProxy */ = {
|
||||
isa = PBXContainerItemProxy;
|
||||
containerPortal = D626645324BBF1C200DF9B88 /* Project object */;
|
||||
proxyType = 1;
|
||||
remoteGlobalIDString = D62664A724BBF26A00DF9B88;
|
||||
remoteInfo = GeminiFormat;
|
||||
};
|
||||
D6E152C524C0004C00FDF9D3 /* PBXContainerItemProxy */ = {
|
||||
isa = PBXContainerItemProxy;
|
||||
containerPortal = D626645324BBF1C200DF9B88 /* Project object */;
|
||||
proxyType = 1;
|
||||
remoteGlobalIDString = D626647624BBF22E00DF9B88;
|
||||
remoteInfo = GeminiProtocol;
|
||||
};
|
||||
D6E152C924C0004C00FDF9D3 /* PBXContainerItemProxy */ = {
|
||||
isa = PBXContainerItemProxy;
|
||||
containerPortal = D626645324BBF1C200DF9B88 /* Project object */;
|
||||
proxyType = 1;
|
||||
remoteGlobalIDString = D62664CD24BC081B00DF9B88;
|
||||
remoteInfo = GeminiRenderer;
|
||||
};
|
||||
D6E152DA24C0007200FDF9D3 /* PBXContainerItemProxy */ = {
|
||||
isa = PBXContainerItemProxy;
|
||||
containerPortal = D626645324BBF1C200DF9B88 /* Project object */;
|
||||
proxyType = 1;
|
||||
remoteGlobalIDString = D6E152CF24C0007200FDF9D3;
|
||||
remoteInfo = BrowserCore;
|
||||
};
|
||||
D6E152DC24C0007200FDF9D3 /* PBXContainerItemProxy */ = {
|
||||
isa = PBXContainerItemProxy;
|
||||
containerPortal = D626645324BBF1C200DF9B88 /* Project object */;
|
||||
proxyType = 1;
|
||||
remoteGlobalIDString = D626645A24BBF1C200DF9B88;
|
||||
remoteInfo = Gemini;
|
||||
};
|
||||
D6E152E324C0007200FDF9D3 /* PBXContainerItemProxy */ = {
|
||||
isa = PBXContainerItemProxy;
|
||||
containerPortal = D626645324BBF1C200DF9B88 /* Project object */;
|
||||
proxyType = 1;
|
||||
remoteGlobalIDString = D6E152CF24C0007200FDF9D3;
|
||||
remoteInfo = BrowserCore;
|
||||
};
|
||||
D6E152EF24C0009300FDF9D3 /* PBXContainerItemProxy */ = {
|
||||
isa = PBXContainerItemProxy;
|
||||
containerPortal = D626645324BBF1C200DF9B88 /* Project object */;
|
||||
proxyType = 1;
|
||||
remoteGlobalIDString = D6E152CF24C0007200FDF9D3;
|
||||
remoteInfo = BrowserCore;
|
||||
};
|
||||
/* End PBXContainerItemProxy section */
|
||||
|
||||
/* Begin PBXCopyFilesBuildPhase section */
|
||||
|
@ -130,6 +201,7 @@
|
|||
files = (
|
||||
D62664E424BC081B00DF9B88 /* GeminiRenderer.framework in Embed Frameworks */,
|
||||
D62664BE24BBF26A00DF9B88 /* GeminiFormat.framework in Embed Frameworks */,
|
||||
D6E152E624C0007200FDF9D3 /* BrowserCore.framework in Embed Frameworks */,
|
||||
D626648D24BBF22E00DF9B88 /* GeminiProtocol.framework in Embed Frameworks */,
|
||||
);
|
||||
name = "Embed Frameworks";
|
||||
|
@ -146,15 +218,28 @@
|
|||
name = "Embed Frameworks";
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
D6E152C224BFFE2500FDF9D3 /* Embed Frameworks */ = {
|
||||
isa = PBXCopyFilesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
dstPath = "";
|
||||
dstSubfolderSpec = 10;
|
||||
files = (
|
||||
D6E152C824C0004C00FDF9D3 /* GeminiRenderer.framework in Embed Frameworks */,
|
||||
D6E152B724BFFE2400FDF9D3 /* GeminiFormat.framework in Embed Frameworks */,
|
||||
D6E152EE24C0009300FDF9D3 /* BrowserCore.framework in Embed Frameworks */,
|
||||
D6E152C424C0004C00FDF9D3 /* GeminiProtocol.framework in Embed Frameworks */,
|
||||
);
|
||||
name = "Embed Frameworks";
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXCopyFilesBuildPhase section */
|
||||
|
||||
/* Begin PBXFileReference section */
|
||||
D626645B24BBF1C200DF9B88 /* Gemini.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Gemini.app; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
D626645E24BBF1C200DF9B88 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
|
||||
D626646024BBF1C200DF9B88 /* ContentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentView.swift; sourceTree = "<group>"; };
|
||||
D626646024BBF1C200DF9B88 /* BrowserView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BrowserView.swift; sourceTree = "<group>"; };
|
||||
D626646224BBF1C300DF9B88 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
|
||||
D626646524BBF1C300DF9B88 /* Preview Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = "Preview Assets.xcassets"; sourceTree = "<group>"; };
|
||||
D626646824BBF1C300DF9B88 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = "<group>"; };
|
||||
D626646A24BBF1C300DF9B88 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||
D626646B24BBF1C300DF9B88 /* Gemini.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = Gemini.entitlements; sourceTree = "<group>"; };
|
||||
D626647724BBF22E00DF9B88 /* GeminiProtocol.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = GeminiProtocol.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
|
@ -192,6 +277,24 @@
|
|||
D69F00AB24BE9DD300E37622 /* GeminiDataTask.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GeminiDataTask.swift; sourceTree = "<group>"; };
|
||||
D69F00AD24BEA29100E37622 /* GeminiResponse.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GeminiResponse.swift; sourceTree = "<group>"; };
|
||||
D69F00AF24BEA84D00E37622 /* NavigationManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NavigationManager.swift; sourceTree = "<group>"; };
|
||||
D6E1529624BFAAA400FDF9D3 /* BrowserWindowController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BrowserWindowController.swift; sourceTree = "<group>"; };
|
||||
D6E1529724BFAAA400FDF9D3 /* BrowserWindowController.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = BrowserWindowController.xib; sourceTree = "<group>"; };
|
||||
D6E1529A24BFAEC700FDF9D3 /* MainMenu.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = MainMenu.xib; sourceTree = "<group>"; };
|
||||
D6E152A224BFFDF500FDF9D3 /* Gemini-iOS.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "Gemini-iOS.app"; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
D6E152A424BFFDF500FDF9D3 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
|
||||
D6E152A624BFFDF500FDF9D3 /* SceneDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SceneDelegate.swift; sourceTree = "<group>"; };
|
||||
D6E152A824BFFDF500FDF9D3 /* ContentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentView.swift; sourceTree = "<group>"; };
|
||||
D6E152AA24BFFDF600FDF9D3 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
|
||||
D6E152AD24BFFDF600FDF9D3 /* Preview Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = "Preview Assets.xcassets"; sourceTree = "<group>"; };
|
||||
D6E152B024BFFDF600FDF9D3 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = "<group>"; };
|
||||
D6E152B224BFFDF600FDF9D3 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||
D6E152D024C0007200FDF9D3 /* BrowserCore.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = BrowserCore.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
D6E152D224C0007200FDF9D3 /* BrowserCore.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = BrowserCore.h; sourceTree = "<group>"; };
|
||||
D6E152D324C0007200FDF9D3 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||
D6E152D824C0007200FDF9D3 /* BrowserCoreTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = BrowserCoreTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
D6E152DF24C0007200FDF9D3 /* BrowserCoreTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BrowserCoreTests.swift; sourceTree = "<group>"; };
|
||||
D6E152E124C0007200FDF9D3 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||
D6E152F324C000DA00FDF9D3 /* ContentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentView.swift; sourceTree = "<group>"; };
|
||||
/* End PBXFileReference section */
|
||||
|
||||
/* Begin PBXFrameworksBuildPhase section */
|
||||
|
@ -201,6 +304,7 @@
|
|||
files = (
|
||||
D62664E324BC081B00DF9B88 /* GeminiRenderer.framework in Frameworks */,
|
||||
D62664BD24BBF26A00DF9B88 /* GeminiFormat.framework in Frameworks */,
|
||||
D6E152E524C0007200FDF9D3 /* BrowserCore.framework in Frameworks */,
|
||||
D626648C24BBF22E00DF9B88 /* GeminiProtocol.framework in Frameworks */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
|
@ -251,6 +355,32 @@
|
|||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
D6E1529F24BFFDF500FDF9D3 /* Frameworks */ = {
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
D6E152C724C0004C00FDF9D3 /* GeminiRenderer.framework in Frameworks */,
|
||||
D6E152B624BFFE2400FDF9D3 /* GeminiFormat.framework in Frameworks */,
|
||||
D6E152ED24C0009300FDF9D3 /* BrowserCore.framework in Frameworks */,
|
||||
D6E152C324C0004C00FDF9D3 /* GeminiProtocol.framework in Frameworks */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
D6E152CD24C0007200FDF9D3 /* Frameworks */ = {
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
D6E152D524C0007200FDF9D3 /* Frameworks */ = {
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
D6E152D924C0007200FDF9D3 /* BrowserCore.framework in Frameworks */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXFrameworksBuildPhase section */
|
||||
|
||||
/* Begin PBXGroup section */
|
||||
|
@ -258,6 +388,9 @@
|
|||
isa = PBXGroup;
|
||||
children = (
|
||||
D626645D24BBF1C200DF9B88 /* Gemini */,
|
||||
D6E152A324BFFDF500FDF9D3 /* Gemini-iOS */,
|
||||
D6E152D124C0007200FDF9D3 /* BrowserCore */,
|
||||
D6E152DE24C0007200FDF9D3 /* BrowserCoreTests */,
|
||||
D626647824BBF22E00DF9B88 /* GeminiProtocol */,
|
||||
D626648524BBF22E00DF9B88 /* GeminiProtocolTests */,
|
||||
D62664A924BBF26A00DF9B88 /* GeminiFormat */,
|
||||
|
@ -279,6 +412,9 @@
|
|||
D62664B024BBF26A00DF9B88 /* GeminiFormatTests.xctest */,
|
||||
D62664CE24BC081B00DF9B88 /* GeminiRenderer.framework */,
|
||||
D62664D624BC081B00DF9B88 /* GeminiRendererTests.xctest */,
|
||||
D6E152A224BFFDF500FDF9D3 /* Gemini-iOS.app */,
|
||||
D6E152D024C0007200FDF9D3 /* BrowserCore.framework */,
|
||||
D6E152D824C0007200FDF9D3 /* BrowserCoreTests.xctest */,
|
||||
);
|
||||
name = Products;
|
||||
sourceTree = "<group>";
|
||||
|
@ -287,10 +423,11 @@
|
|||
isa = PBXGroup;
|
||||
children = (
|
||||
D626645E24BBF1C200DF9B88 /* AppDelegate.swift */,
|
||||
D626646024BBF1C200DF9B88 /* ContentView.swift */,
|
||||
D69F00AF24BEA84D00E37622 /* NavigationManager.swift */,
|
||||
D6E1529A24BFAEC700FDF9D3 /* MainMenu.xib */,
|
||||
D6E152F324C000DA00FDF9D3 /* ContentView.swift */,
|
||||
D6E1529624BFAAA400FDF9D3 /* BrowserWindowController.swift */,
|
||||
D6E1529724BFAAA400FDF9D3 /* BrowserWindowController.xib */,
|
||||
D626646224BBF1C300DF9B88 /* Assets.xcassets */,
|
||||
D626646724BBF1C300DF9B88 /* Main.storyboard */,
|
||||
D626646A24BBF1C300DF9B88 /* Info.plist */,
|
||||
D626646B24BBF1C300DF9B88 /* Gemini.entitlements */,
|
||||
D626646424BBF1C300DF9B88 /* Preview Content */,
|
||||
|
@ -383,6 +520,48 @@
|
|||
name = Frameworks;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
D6E152A324BFFDF500FDF9D3 /* Gemini-iOS */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
D6E152A424BFFDF500FDF9D3 /* AppDelegate.swift */,
|
||||
D6E152A624BFFDF500FDF9D3 /* SceneDelegate.swift */,
|
||||
D6E152A824BFFDF500FDF9D3 /* ContentView.swift */,
|
||||
D6E152AA24BFFDF600FDF9D3 /* Assets.xcassets */,
|
||||
D6E152AF24BFFDF600FDF9D3 /* LaunchScreen.storyboard */,
|
||||
D6E152B224BFFDF600FDF9D3 /* Info.plist */,
|
||||
D6E152AC24BFFDF600FDF9D3 /* Preview Content */,
|
||||
);
|
||||
path = "Gemini-iOS";
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
D6E152AC24BFFDF600FDF9D3 /* Preview Content */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
D6E152AD24BFFDF600FDF9D3 /* Preview Assets.xcassets */,
|
||||
);
|
||||
path = "Preview Content";
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
D6E152D124C0007200FDF9D3 /* BrowserCore */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
D6E152D224C0007200FDF9D3 /* BrowserCore.h */,
|
||||
D6E152D324C0007200FDF9D3 /* Info.plist */,
|
||||
D69F00AF24BEA84D00E37622 /* NavigationManager.swift */,
|
||||
D626646024BBF1C200DF9B88 /* BrowserView.swift */,
|
||||
);
|
||||
path = BrowserCore;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
D6E152DE24C0007200FDF9D3 /* BrowserCoreTests */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
D6E152DF24C0007200FDF9D3 /* BrowserCoreTests.swift */,
|
||||
D6E152E124C0007200FDF9D3 /* Info.plist */,
|
||||
);
|
||||
path = BrowserCoreTests;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
/* End PBXGroup section */
|
||||
|
||||
/* Begin PBXHeadersBuildPhase section */
|
||||
|
@ -410,6 +589,14 @@
|
|||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
D6E152CB24C0007200FDF9D3 /* Headers */ = {
|
||||
isa = PBXHeadersBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
D6E152E224C0007200FDF9D3 /* BrowserCore.h in Headers */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXHeadersBuildPhase section */
|
||||
|
||||
/* Begin PBXNativeTarget section */
|
||||
|
@ -428,6 +615,7 @@
|
|||
D626648B24BBF22E00DF9B88 /* PBXTargetDependency */,
|
||||
D62664BC24BBF26A00DF9B88 /* PBXTargetDependency */,
|
||||
D62664E224BC081B00DF9B88 /* PBXTargetDependency */,
|
||||
D6E152E424C0007200FDF9D3 /* PBXTargetDependency */,
|
||||
);
|
||||
name = Gemini;
|
||||
productName = Gemini;
|
||||
|
@ -547,6 +735,65 @@
|
|||
productReference = D62664D624BC081B00DF9B88 /* GeminiRendererTests.xctest */;
|
||||
productType = "com.apple.product-type.bundle.unit-test";
|
||||
};
|
||||
D6E152A124BFFDF500FDF9D3 /* Gemini-iOS */ = {
|
||||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = D6E152B324BFFDF600FDF9D3 /* Build configuration list for PBXNativeTarget "Gemini-iOS" */;
|
||||
buildPhases = (
|
||||
D6E1529E24BFFDF500FDF9D3 /* Sources */,
|
||||
D6E1529F24BFFDF500FDF9D3 /* Frameworks */,
|
||||
D6E152A024BFFDF500FDF9D3 /* Resources */,
|
||||
D6E152C224BFFE2500FDF9D3 /* Embed Frameworks */,
|
||||
);
|
||||
buildRules = (
|
||||
);
|
||||
dependencies = (
|
||||
D6E152B924BFFE2400FDF9D3 /* PBXTargetDependency */,
|
||||
D6E152C624C0004C00FDF9D3 /* PBXTargetDependency */,
|
||||
D6E152CA24C0004C00FDF9D3 /* PBXTargetDependency */,
|
||||
D6E152F024C0009300FDF9D3 /* PBXTargetDependency */,
|
||||
);
|
||||
name = "Gemini-iOS";
|
||||
productName = "Gemini-iOS";
|
||||
productReference = D6E152A224BFFDF500FDF9D3 /* Gemini-iOS.app */;
|
||||
productType = "com.apple.product-type.application";
|
||||
};
|
||||
D6E152CF24C0007200FDF9D3 /* BrowserCore */ = {
|
||||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = D6E152E724C0007200FDF9D3 /* Build configuration list for PBXNativeTarget "BrowserCore" */;
|
||||
buildPhases = (
|
||||
D6E152CB24C0007200FDF9D3 /* Headers */,
|
||||
D6E152CC24C0007200FDF9D3 /* Sources */,
|
||||
D6E152CD24C0007200FDF9D3 /* Frameworks */,
|
||||
D6E152CE24C0007200FDF9D3 /* Resources */,
|
||||
);
|
||||
buildRules = (
|
||||
);
|
||||
dependencies = (
|
||||
);
|
||||
name = BrowserCore;
|
||||
productName = BrowserCore;
|
||||
productReference = D6E152D024C0007200FDF9D3 /* BrowserCore.framework */;
|
||||
productType = "com.apple.product-type.framework";
|
||||
};
|
||||
D6E152D724C0007200FDF9D3 /* BrowserCoreTests */ = {
|
||||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = D6E152EA24C0007200FDF9D3 /* Build configuration list for PBXNativeTarget "BrowserCoreTests" */;
|
||||
buildPhases = (
|
||||
D6E152D424C0007200FDF9D3 /* Sources */,
|
||||
D6E152D524C0007200FDF9D3 /* Frameworks */,
|
||||
D6E152D624C0007200FDF9D3 /* Resources */,
|
||||
);
|
||||
buildRules = (
|
||||
);
|
||||
dependencies = (
|
||||
D6E152DB24C0007200FDF9D3 /* PBXTargetDependency */,
|
||||
D6E152DD24C0007200FDF9D3 /* PBXTargetDependency */,
|
||||
);
|
||||
name = BrowserCoreTests;
|
||||
productName = BrowserCoreTests;
|
||||
productReference = D6E152D824C0007200FDF9D3 /* BrowserCoreTests.xctest */;
|
||||
productType = "com.apple.product-type.bundle.unit-test";
|
||||
};
|
||||
/* End PBXNativeTarget section */
|
||||
|
||||
/* Begin PBXProject section */
|
||||
|
@ -583,6 +830,16 @@
|
|||
CreatedOnToolsVersion = 12.0;
|
||||
TestTargetID = D626645A24BBF1C200DF9B88;
|
||||
};
|
||||
D6E152A124BFFDF500FDF9D3 = {
|
||||
CreatedOnToolsVersion = 12.0;
|
||||
};
|
||||
D6E152CF24C0007200FDF9D3 = {
|
||||
CreatedOnToolsVersion = 12.0;
|
||||
};
|
||||
D6E152D724C0007200FDF9D3 = {
|
||||
CreatedOnToolsVersion = 12.0;
|
||||
TestTargetID = D626645A24BBF1C200DF9B88;
|
||||
};
|
||||
};
|
||||
};
|
||||
buildConfigurationList = D626645624BBF1C200DF9B88 /* Build configuration list for PBXProject "Gemini" */;
|
||||
|
@ -599,12 +856,15 @@
|
|||
projectRoot = "";
|
||||
targets = (
|
||||
D626645A24BBF1C200DF9B88 /* Gemini */,
|
||||
D6E152A124BFFDF500FDF9D3 /* Gemini-iOS */,
|
||||
D626647624BBF22E00DF9B88 /* GeminiProtocol */,
|
||||
D626647E24BBF22E00DF9B88 /* GeminiProtocolTests */,
|
||||
D62664A724BBF26A00DF9B88 /* GeminiFormat */,
|
||||
D62664AF24BBF26A00DF9B88 /* GeminiFormatTests */,
|
||||
D62664CD24BC081B00DF9B88 /* GeminiRenderer */,
|
||||
D62664D524BC081B00DF9B88 /* GeminiRendererTests */,
|
||||
D6E152CF24C0007200FDF9D3 /* BrowserCore */,
|
||||
D6E152D724C0007200FDF9D3 /* BrowserCoreTests */,
|
||||
);
|
||||
};
|
||||
/* End PBXProject section */
|
||||
|
@ -614,9 +874,10 @@
|
|||
isa = PBXResourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
D626646924BBF1C300DF9B88 /* Main.storyboard in Resources */,
|
||||
D6E1529924BFAAA400FDF9D3 /* BrowserWindowController.xib in Resources */,
|
||||
D626646624BBF1C300DF9B88 /* Preview Assets.xcassets in Resources */,
|
||||
D626646324BBF1C300DF9B88 /* Assets.xcassets in Resources */,
|
||||
D6E1529B24BFAEC700FDF9D3 /* MainMenu.xib in Resources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
|
@ -662,6 +923,30 @@
|
|||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
D6E152A024BFFDF500FDF9D3 /* Resources */ = {
|
||||
isa = PBXResourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
D6E152B124BFFDF600FDF9D3 /* LaunchScreen.storyboard in Resources */,
|
||||
D6E152AE24BFFDF600FDF9D3 /* Preview Assets.xcassets in Resources */,
|
||||
D6E152AB24BFFDF600FDF9D3 /* Assets.xcassets in Resources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
D6E152CE24C0007200FDF9D3 /* Resources */ = {
|
||||
isa = PBXResourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
D6E152D624C0007200FDF9D3 /* Resources */ = {
|
||||
isa = PBXResourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXResourcesBuildPhase section */
|
||||
|
||||
/* Begin PBXSourcesBuildPhase section */
|
||||
|
@ -669,9 +954,9 @@
|
|||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
D626646124BBF1C200DF9B88 /* ContentView.swift in Sources */,
|
||||
D6E1529824BFAAA400FDF9D3 /* BrowserWindowController.swift in Sources */,
|
||||
D626645F24BBF1C200DF9B88 /* AppDelegate.swift in Sources */,
|
||||
D69F00B024BEA84D00E37622 /* NavigationManager.swift in Sources */,
|
||||
D6E152F424C000DA00FDF9D3 /* ContentView.swift in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
|
@ -736,6 +1021,33 @@
|
|||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
D6E1529E24BFFDF500FDF9D3 /* Sources */ = {
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
D6E152A524BFFDF500FDF9D3 /* AppDelegate.swift in Sources */,
|
||||
D6E152A724BFFDF500FDF9D3 /* SceneDelegate.swift in Sources */,
|
||||
D6E152A924BFFDF500FDF9D3 /* ContentView.swift in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
D6E152CC24C0007200FDF9D3 /* Sources */ = {
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
D6E152F124C000A000FDF9D3 /* NavigationManager.swift in Sources */,
|
||||
D6E152F224C000CD00FDF9D3 /* BrowserView.swift in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
D6E152D424C0007200FDF9D3 /* Sources */ = {
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
D6E152E024C0007200FDF9D3 /* BrowserCoreTests.swift in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXSourcesBuildPhase section */
|
||||
|
||||
/* Begin PBXTargetDependency section */
|
||||
|
@ -789,15 +1101,50 @@
|
|||
target = D62664A724BBF26A00DF9B88 /* GeminiFormat */;
|
||||
targetProxy = D62664F224BC0D7700DF9B88 /* PBXContainerItemProxy */;
|
||||
};
|
||||
D6E152B924BFFE2400FDF9D3 /* PBXTargetDependency */ = {
|
||||
isa = PBXTargetDependency;
|
||||
target = D62664A724BBF26A00DF9B88 /* GeminiFormat */;
|
||||
targetProxy = D6E152B824BFFE2400FDF9D3 /* PBXContainerItemProxy */;
|
||||
};
|
||||
D6E152C624C0004C00FDF9D3 /* PBXTargetDependency */ = {
|
||||
isa = PBXTargetDependency;
|
||||
target = D626647624BBF22E00DF9B88 /* GeminiProtocol */;
|
||||
targetProxy = D6E152C524C0004C00FDF9D3 /* PBXContainerItemProxy */;
|
||||
};
|
||||
D6E152CA24C0004C00FDF9D3 /* PBXTargetDependency */ = {
|
||||
isa = PBXTargetDependency;
|
||||
target = D62664CD24BC081B00DF9B88 /* GeminiRenderer */;
|
||||
targetProxy = D6E152C924C0004C00FDF9D3 /* PBXContainerItemProxy */;
|
||||
};
|
||||
D6E152DB24C0007200FDF9D3 /* PBXTargetDependency */ = {
|
||||
isa = PBXTargetDependency;
|
||||
target = D6E152CF24C0007200FDF9D3 /* BrowserCore */;
|
||||
targetProxy = D6E152DA24C0007200FDF9D3 /* PBXContainerItemProxy */;
|
||||
};
|
||||
D6E152DD24C0007200FDF9D3 /* PBXTargetDependency */ = {
|
||||
isa = PBXTargetDependency;
|
||||
target = D626645A24BBF1C200DF9B88 /* Gemini */;
|
||||
targetProxy = D6E152DC24C0007200FDF9D3 /* PBXContainerItemProxy */;
|
||||
};
|
||||
D6E152E424C0007200FDF9D3 /* PBXTargetDependency */ = {
|
||||
isa = PBXTargetDependency;
|
||||
target = D6E152CF24C0007200FDF9D3 /* BrowserCore */;
|
||||
targetProxy = D6E152E324C0007200FDF9D3 /* PBXContainerItemProxy */;
|
||||
};
|
||||
D6E152F024C0009300FDF9D3 /* PBXTargetDependency */ = {
|
||||
isa = PBXTargetDependency;
|
||||
target = D6E152CF24C0007200FDF9D3 /* BrowserCore */;
|
||||
targetProxy = D6E152EF24C0009300FDF9D3 /* PBXContainerItemProxy */;
|
||||
};
|
||||
/* End PBXTargetDependency section */
|
||||
|
||||
/* Begin PBXVariantGroup section */
|
||||
D626646724BBF1C300DF9B88 /* Main.storyboard */ = {
|
||||
D6E152AF24BFFDF600FDF9D3 /* LaunchScreen.storyboard */ = {
|
||||
isa = PBXVariantGroup;
|
||||
children = (
|
||||
D626646824BBF1C300DF9B88 /* Base */,
|
||||
D6E152B024BFFDF600FDF9D3 /* Base */,
|
||||
);
|
||||
name = Main.storyboard;
|
||||
name = LaunchScreen.storyboard;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
/* End PBXVariantGroup section */
|
||||
|
@ -982,6 +1329,7 @@
|
|||
DYLIB_INSTALL_NAME_BASE = "@rpath";
|
||||
INFOPLIST_FILE = GeminiProtocol/Info.plist;
|
||||
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 13.5;
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"@executable_path/../Frameworks",
|
||||
|
@ -991,8 +1339,10 @@
|
|||
PRODUCT_BUNDLE_IDENTIFIER = net.shadowfacts.GeminiProtocol;
|
||||
PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)";
|
||||
SKIP_INSTALL = YES;
|
||||
SUPPORTED_PLATFORMS = "macosx iphonesimulator iphoneos";
|
||||
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
|
||||
SWIFT_VERSION = 5.0;
|
||||
VALID_ARCHS = "x86_64 arm64 armv7s armv7 arm64e";
|
||||
VERSIONING_SYSTEM = "apple-generic";
|
||||
VERSION_INFO_PREFIX = "";
|
||||
};
|
||||
|
@ -1012,6 +1362,7 @@
|
|||
DYLIB_INSTALL_NAME_BASE = "@rpath";
|
||||
INFOPLIST_FILE = GeminiProtocol/Info.plist;
|
||||
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 13.5;
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"@executable_path/../Frameworks",
|
||||
|
@ -1021,7 +1372,9 @@
|
|||
PRODUCT_BUNDLE_IDENTIFIER = net.shadowfacts.GeminiProtocol;
|
||||
PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)";
|
||||
SKIP_INSTALL = YES;
|
||||
SUPPORTED_PLATFORMS = "macosx iphonesimulator iphoneos";
|
||||
SWIFT_VERSION = 5.0;
|
||||
VALID_ARCHS = "x86_64 arm64 armv7s armv7 arm64e";
|
||||
VERSIONING_SYSTEM = "apple-generic";
|
||||
VERSION_INFO_PREFIX = "";
|
||||
};
|
||||
|
@ -1081,6 +1434,7 @@
|
|||
DYLIB_INSTALL_NAME_BASE = "@rpath";
|
||||
INFOPLIST_FILE = GeminiFormat/Info.plist;
|
||||
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 13.5;
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"@executable_path/../Frameworks",
|
||||
|
@ -1090,8 +1444,10 @@
|
|||
PRODUCT_BUNDLE_IDENTIFIER = net.shadowfacts.GeminiFormat;
|
||||
PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)";
|
||||
SKIP_INSTALL = YES;
|
||||
SUPPORTED_PLATFORMS = "macosx iphonesimulator iphoneos";
|
||||
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
|
||||
SWIFT_VERSION = 5.0;
|
||||
VALID_ARCHS = "x86_64 arm64 armv7s armv7 arm64e";
|
||||
VERSIONING_SYSTEM = "apple-generic";
|
||||
VERSION_INFO_PREFIX = "";
|
||||
};
|
||||
|
@ -1111,6 +1467,7 @@
|
|||
DYLIB_INSTALL_NAME_BASE = "@rpath";
|
||||
INFOPLIST_FILE = GeminiFormat/Info.plist;
|
||||
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 13.5;
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"@executable_path/../Frameworks",
|
||||
|
@ -1120,7 +1477,9 @@
|
|||
PRODUCT_BUNDLE_IDENTIFIER = net.shadowfacts.GeminiFormat;
|
||||
PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)";
|
||||
SKIP_INSTALL = YES;
|
||||
SUPPORTED_PLATFORMS = "macosx iphonesimulator iphoneos";
|
||||
SWIFT_VERSION = 5.0;
|
||||
VALID_ARCHS = "x86_64 arm64 armv7s armv7 arm64e";
|
||||
VERSIONING_SYSTEM = "apple-generic";
|
||||
VERSION_INFO_PREFIX = "";
|
||||
};
|
||||
|
@ -1180,6 +1539,7 @@
|
|||
DYLIB_INSTALL_NAME_BASE = "@rpath";
|
||||
INFOPLIST_FILE = GeminiRenderer/Info.plist;
|
||||
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 13.5;
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"@executable_path/../Frameworks",
|
||||
|
@ -1189,8 +1549,10 @@
|
|||
PRODUCT_BUNDLE_IDENTIFIER = net.shadowfacts.GeminiRenderer;
|
||||
PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)";
|
||||
SKIP_INSTALL = YES;
|
||||
SUPPORTED_PLATFORMS = "macosx iphonesimulator iphoneos";
|
||||
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
|
||||
SWIFT_VERSION = 5.0;
|
||||
VALID_ARCHS = "x86_64 arm64 armv7s armv7 arm64e";
|
||||
VERSIONING_SYSTEM = "apple-generic";
|
||||
VERSION_INFO_PREFIX = "";
|
||||
};
|
||||
|
@ -1210,6 +1572,7 @@
|
|||
DYLIB_INSTALL_NAME_BASE = "@rpath";
|
||||
INFOPLIST_FILE = GeminiRenderer/Info.plist;
|
||||
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 13.5;
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"@executable_path/../Frameworks",
|
||||
|
@ -1219,7 +1582,9 @@
|
|||
PRODUCT_BUNDLE_IDENTIFIER = net.shadowfacts.GeminiRenderer;
|
||||
PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)";
|
||||
SKIP_INSTALL = YES;
|
||||
SUPPORTED_PLATFORMS = "macosx iphonesimulator iphoneos";
|
||||
SWIFT_VERSION = 5.0;
|
||||
VALID_ARCHS = "x86_64 arm64 armv7s armv7 arm64e";
|
||||
VERSIONING_SYSTEM = "apple-generic";
|
||||
VERSION_INFO_PREFIX = "";
|
||||
};
|
||||
|
@ -1265,6 +1630,157 @@
|
|||
};
|
||||
name = Release;
|
||||
};
|
||||
D6E152B424BFFDF600FDF9D3 /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
DEVELOPMENT_ASSET_PATHS = "\"Gemini-iOS/Preview Content\"";
|
||||
DEVELOPMENT_TEAM = HGYVAQA9FW;
|
||||
ENABLE_PREVIEWS = YES;
|
||||
INFOPLIST_FILE = "Gemini-iOS/Info.plist";
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 13.5;
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"@executable_path/Frameworks",
|
||||
);
|
||||
PRODUCT_BUNDLE_IDENTIFIER = "net.shadowfacts.Gemini-iOS";
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SDKROOT = iphoneos;
|
||||
SWIFT_VERSION = 5.0;
|
||||
TARGETED_DEVICE_FAMILY = "1,2";
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
D6E152B524BFFDF600FDF9D3 /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
DEVELOPMENT_ASSET_PATHS = "\"Gemini-iOS/Preview Content\"";
|
||||
DEVELOPMENT_TEAM = HGYVAQA9FW;
|
||||
ENABLE_PREVIEWS = YES;
|
||||
INFOPLIST_FILE = "Gemini-iOS/Info.plist";
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 13.5;
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"@executable_path/Frameworks",
|
||||
);
|
||||
PRODUCT_BUNDLE_IDENTIFIER = "net.shadowfacts.Gemini-iOS";
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SDKROOT = iphoneos;
|
||||
SWIFT_VERSION = 5.0;
|
||||
TARGETED_DEVICE_FAMILY = "1,2";
|
||||
VALIDATE_PRODUCT = YES;
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
D6E152E824C0007200FDF9D3 /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
COMBINE_HIDPI_IMAGES = YES;
|
||||
CURRENT_PROJECT_VERSION = 1;
|
||||
DEFINES_MODULE = YES;
|
||||
DEVELOPMENT_TEAM = HGYVAQA9FW;
|
||||
DYLIB_COMPATIBILITY_VERSION = 1;
|
||||
DYLIB_CURRENT_VERSION = 1;
|
||||
DYLIB_INSTALL_NAME_BASE = "@rpath";
|
||||
INFOPLIST_FILE = BrowserCore/Info.plist;
|
||||
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 13.5;
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"@executable_path/../Frameworks",
|
||||
"@loader_path/Frameworks",
|
||||
);
|
||||
MACOSX_DEPLOYMENT_TARGET = 10.15;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = net.shadowfacts.BrowserCore;
|
||||
PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)";
|
||||
SKIP_INSTALL = YES;
|
||||
SUPPORTED_PLATFORMS = "macosx iphonesimulator iphoneos";
|
||||
SWIFT_VERSION = 5.0;
|
||||
VALID_ARCHS = "x86_64 arm64 armv7s armv7 arm64e";
|
||||
VERSIONING_SYSTEM = "apple-generic";
|
||||
VERSION_INFO_PREFIX = "";
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
D6E152E924C0007200FDF9D3 /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
COMBINE_HIDPI_IMAGES = YES;
|
||||
CURRENT_PROJECT_VERSION = 1;
|
||||
DEFINES_MODULE = YES;
|
||||
DEVELOPMENT_TEAM = HGYVAQA9FW;
|
||||
DYLIB_COMPATIBILITY_VERSION = 1;
|
||||
DYLIB_CURRENT_VERSION = 1;
|
||||
DYLIB_INSTALL_NAME_BASE = "@rpath";
|
||||
INFOPLIST_FILE = BrowserCore/Info.plist;
|
||||
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 13.5;
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"@executable_path/../Frameworks",
|
||||
"@loader_path/Frameworks",
|
||||
);
|
||||
MACOSX_DEPLOYMENT_TARGET = 10.15;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = net.shadowfacts.BrowserCore;
|
||||
PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)";
|
||||
SKIP_INSTALL = YES;
|
||||
SUPPORTED_PLATFORMS = "macosx iphonesimulator iphoneos";
|
||||
SWIFT_VERSION = 5.0;
|
||||
VALID_ARCHS = "x86_64 arm64 armv7s armv7 arm64e";
|
||||
VERSIONING_SYSTEM = "apple-generic";
|
||||
VERSION_INFO_PREFIX = "";
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
D6E152EB24C0007200FDF9D3 /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
COMBINE_HIDPI_IMAGES = YES;
|
||||
DEVELOPMENT_TEAM = HGYVAQA9FW;
|
||||
INFOPLIST_FILE = BrowserCoreTests/Info.plist;
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"@executable_path/../Frameworks",
|
||||
"@loader_path/../Frameworks",
|
||||
);
|
||||
PRODUCT_BUNDLE_IDENTIFIER = net.shadowfacts.BrowserCoreTests;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SWIFT_VERSION = 5.0;
|
||||
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Gemini.app/Contents/MacOS/Gemini";
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
D6E152EC24C0007200FDF9D3 /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
COMBINE_HIDPI_IMAGES = YES;
|
||||
DEVELOPMENT_TEAM = HGYVAQA9FW;
|
||||
INFOPLIST_FILE = BrowserCoreTests/Info.plist;
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"@executable_path/../Frameworks",
|
||||
"@loader_path/../Frameworks",
|
||||
);
|
||||
PRODUCT_BUNDLE_IDENTIFIER = net.shadowfacts.BrowserCoreTests;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SWIFT_VERSION = 5.0;
|
||||
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Gemini.app/Contents/MacOS/Gemini";
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
/* End XCBuildConfiguration section */
|
||||
|
||||
/* Begin XCConfigurationList section */
|
||||
|
@ -1340,6 +1856,33 @@
|
|||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
D6E152B324BFFDF600FDF9D3 /* Build configuration list for PBXNativeTarget "Gemini-iOS" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
D6E152B424BFFDF600FDF9D3 /* Debug */,
|
||||
D6E152B524BFFDF600FDF9D3 /* Release */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
D6E152E724C0007200FDF9D3 /* Build configuration list for PBXNativeTarget "BrowserCore" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
D6E152E824C0007200FDF9D3 /* Debug */,
|
||||
D6E152E924C0007200FDF9D3 /* Release */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
D6E152EA24C0007200FDF9D3 /* Build configuration list for PBXNativeTarget "BrowserCoreTests" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
D6E152EB24C0007200FDF9D3 /* Debug */,
|
||||
D6E152EC24C0007200FDF9D3 /* Release */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
/* End XCConfigurationList section */
|
||||
};
|
||||
rootObject = D626645324BBF1C200DF9B88 /* Project object */;
|
||||
|
|
|
@ -58,6 +58,16 @@
|
|||
ReferencedContainer = "container:Gemini.xcodeproj">
|
||||
</BuildableReference>
|
||||
</TestableReference>
|
||||
<TestableReference
|
||||
skipped = "NO">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "D6E152D724C0007200FDF9D3"
|
||||
BuildableName = "BrowserCoreTests.xctest"
|
||||
BlueprintName = "BrowserCoreTests"
|
||||
ReferencedContainer = "container:Gemini.xcodeproj">
|
||||
</BuildableReference>
|
||||
</TestableReference>
|
||||
</Testables>
|
||||
</TestAction>
|
||||
<LaunchAction
|
||||
|
|
|
@ -4,6 +4,16 @@
|
|||
<dict>
|
||||
<key>SchemeUserState</key>
|
||||
<dict>
|
||||
<key>BrowserCore.xcscheme_^#shared#^_</key>
|
||||
<dict>
|
||||
<key>orderHint</key>
|
||||
<integer>5</integer>
|
||||
</dict>
|
||||
<key>Gemini-iOS.xcscheme_^#shared#^_</key>
|
||||
<dict>
|
||||
<key>orderHint</key>
|
||||
<integer>2</integer>
|
||||
</dict>
|
||||
<key>Gemini.xcscheme_^#shared#^_</key>
|
||||
<dict>
|
||||
<key>orderHint</key>
|
||||
|
@ -22,7 +32,7 @@
|
|||
<key>GeminiRenderer.xcscheme_^#shared#^_</key>
|
||||
<dict>
|
||||
<key>orderHint</key>
|
||||
<integer>2</integer>
|
||||
<integer>4</integer>
|
||||
</dict>
|
||||
</dict>
|
||||
<key>SuppressBuildableAutocreation</key>
|
||||
|
|
|
@ -8,34 +8,40 @@
|
|||
import Cocoa
|
||||
import SwiftUI
|
||||
import GeminiProtocol
|
||||
import Combine
|
||||
|
||||
@NSApplicationMain
|
||||
class AppDelegate: NSObject, NSApplicationDelegate {
|
||||
|
||||
var windowControllers = [BrowserWindowController]()
|
||||
|
||||
var window: NSWindow!
|
||||
|
||||
let homePage = URL(string: "gemini://gemini.circumlunar.space/")!
|
||||
private(set) lazy var navigationManager = NavigationManager(url: homePage)
|
||||
static let homePage = URL(string: "gemini://gemini.circumlunar.space/")!
|
||||
|
||||
func applicationDidFinishLaunching(_ aNotification: Notification) {
|
||||
// Create the SwiftUI view that provides the window contents.
|
||||
let contentView = ContentView(navigator: navigationManager)
|
||||
|
||||
// Create the window and set the content view.
|
||||
window = NSWindow(
|
||||
contentRect: NSRect(x: 0, y: 0, width: 480, height: 300),
|
||||
styleMask: [.titled, .closable, .miniaturizable, .resizable, .fullSizeContentView],
|
||||
backing: .buffered, defer: false)
|
||||
window.isReleasedWhenClosed = false
|
||||
window.center()
|
||||
window.setFrameAutosaveName("Main Window")
|
||||
window.contentView = NSHostingView(rootView: contentView)
|
||||
window.title = "Gemini"
|
||||
window.makeKeyAndOrderFront(nil)
|
||||
let wc = BrowserWindowController()
|
||||
windowControllers.append(wc)
|
||||
wc.showWindow(nil)
|
||||
}
|
||||
|
||||
func applicationWillTerminate(_ aNotification: Notification) {
|
||||
// Insert code here to tear down your application
|
||||
}
|
||||
|
||||
func createNewWindowTab(attachedTo existingWindow: NSWindow) {
|
||||
let wc = BrowserWindowController()
|
||||
windowControllers.append(wc)
|
||||
|
||||
if let tabGroup = existingWindow.tabGroup {
|
||||
wc.window!.setFrame(existingWindow.frame, display: false)
|
||||
tabGroup.addWindow(wc.window!)
|
||||
tabGroup.selectedWindow = wc.window!
|
||||
}
|
||||
}
|
||||
|
||||
@IBAction func newTab(_ sender: Any?) {
|
||||
if let keyWindow = windowControllers.first(where: { $0.window != nil && $0.window!.isKeyWindow })?.window {
|
||||
createNewWindowTab(attachedTo: keyWindow)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,683 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<document type="com.apple.InterfaceBuilder3.Cocoa.Storyboard.XIB" version="3.0" toolsVersion="14814" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES">
|
||||
<dependencies>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="14814"/>
|
||||
</dependencies>
|
||||
<scenes>
|
||||
<!--Application-->
|
||||
<scene sceneID="JPo-4y-FX3">
|
||||
<objects>
|
||||
<application id="hnw-xV-0zn" sceneMemberID="viewController">
|
||||
<menu key="mainMenu" title="Main Menu" systemMenu="main" id="AYu-sK-qS6">
|
||||
<items>
|
||||
<menuItem title="Gemini" id="1Xt-HY-uBw">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<menu key="submenu" title="Gemini" systemMenu="apple" id="uQy-DD-JDr">
|
||||
<items>
|
||||
<menuItem title="About Gemini" id="5kV-Vb-QxS">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="orderFrontStandardAboutPanel:" target="Ady-hI-5gd" id="Exp-CZ-Vem"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem isSeparatorItem="YES" id="VOq-y0-SEH"/>
|
||||
<menuItem title="Preferences…" keyEquivalent="," id="BOF-NM-1cW"/>
|
||||
<menuItem isSeparatorItem="YES" id="wFC-TO-SCJ"/>
|
||||
<menuItem title="Services" id="NMo-om-nkz">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<menu key="submenu" title="Services" systemMenu="services" id="hz9-B4-Xy5"/>
|
||||
</menuItem>
|
||||
<menuItem isSeparatorItem="YES" id="4je-JR-u6R"/>
|
||||
<menuItem title="Hide Gemini" keyEquivalent="h" id="Olw-nP-bQN">
|
||||
<connections>
|
||||
<action selector="hide:" target="Ady-hI-5gd" id="PnN-Uc-m68"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Hide Others" keyEquivalent="h" id="Vdr-fp-XzO">
|
||||
<modifierMask key="keyEquivalentModifierMask" option="YES" command="YES"/>
|
||||
<connections>
|
||||
<action selector="hideOtherApplications:" target="Ady-hI-5gd" id="VT4-aY-XCT"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Show All" id="Kd2-mp-pUS">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="unhideAllApplications:" target="Ady-hI-5gd" id="Dhg-Le-xox"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem isSeparatorItem="YES" id="kCx-OE-vgT"/>
|
||||
<menuItem title="Quit Gemini" keyEquivalent="q" id="4sb-4s-VLi">
|
||||
<connections>
|
||||
<action selector="terminate:" target="Ady-hI-5gd" id="Te7-pn-YzF"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
</items>
|
||||
</menu>
|
||||
</menuItem>
|
||||
<menuItem title="File" id="dMs-cI-mzQ">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<menu key="submenu" title="File" id="bib-Uj-vzu">
|
||||
<items>
|
||||
<menuItem title="New" keyEquivalent="n" id="Was-JA-tGl">
|
||||
<connections>
|
||||
<action selector="newDocument:" target="Ady-hI-5gd" id="4Si-XN-c54"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Open…" keyEquivalent="o" id="IAo-SY-fd9">
|
||||
<connections>
|
||||
<action selector="openDocument:" target="Ady-hI-5gd" id="bVn-NM-KNZ"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Open Recent" id="tXI-mr-wws">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<menu key="submenu" title="Open Recent" systemMenu="recentDocuments" id="oas-Oc-fiZ">
|
||||
<items>
|
||||
<menuItem title="Clear Menu" id="vNY-rz-j42">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="clearRecentDocuments:" target="Ady-hI-5gd" id="Daa-9d-B3U"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
</items>
|
||||
</menu>
|
||||
</menuItem>
|
||||
<menuItem isSeparatorItem="YES" id="m54-Is-iLE"/>
|
||||
<menuItem title="Close" keyEquivalent="w" id="DVo-aG-piG">
|
||||
<connections>
|
||||
<action selector="performClose:" target="Ady-hI-5gd" id="HmO-Ls-i7Q"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Save…" keyEquivalent="s" id="pxx-59-PXV">
|
||||
<connections>
|
||||
<action selector="saveDocument:" target="Ady-hI-5gd" id="teZ-XB-qJY"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Save As…" keyEquivalent="S" id="Bw7-FT-i3A">
|
||||
<connections>
|
||||
<action selector="saveDocumentAs:" target="Ady-hI-5gd" id="mDf-zr-I0C"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Revert to Saved" keyEquivalent="r" id="KaW-ft-85H">
|
||||
<connections>
|
||||
<action selector="revertDocumentToSaved:" target="Ady-hI-5gd" id="iJ3-Pv-kwq"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem isSeparatorItem="YES" id="aJh-i4-bef"/>
|
||||
<menuItem title="Page Setup…" keyEquivalent="P" id="qIS-W8-SiK">
|
||||
<modifierMask key="keyEquivalentModifierMask" shift="YES" command="YES"/>
|
||||
<connections>
|
||||
<action selector="runPageLayout:" target="Ady-hI-5gd" id="Din-rz-gC5"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Print…" keyEquivalent="p" id="aTl-1u-JFS">
|
||||
<connections>
|
||||
<action selector="print:" target="Ady-hI-5gd" id="qaZ-4w-aoO"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
</items>
|
||||
</menu>
|
||||
</menuItem>
|
||||
<menuItem title="Edit" id="5QF-Oa-p0T">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<menu key="submenu" title="Edit" id="W48-6f-4Dl">
|
||||
<items>
|
||||
<menuItem title="Undo" keyEquivalent="z" id="dRJ-4n-Yzg">
|
||||
<connections>
|
||||
<action selector="undo:" target="Ady-hI-5gd" id="M6e-cu-g7V"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Redo" keyEquivalent="Z" id="6dh-zS-Vam">
|
||||
<connections>
|
||||
<action selector="redo:" target="Ady-hI-5gd" id="oIA-Rs-6OD"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem isSeparatorItem="YES" id="WRV-NI-Exz"/>
|
||||
<menuItem title="Cut" keyEquivalent="x" id="uRl-iY-unG">
|
||||
<connections>
|
||||
<action selector="cut:" target="Ady-hI-5gd" id="YJe-68-I9s"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Copy" keyEquivalent="c" id="x3v-GG-iWU">
|
||||
<connections>
|
||||
<action selector="copy:" target="Ady-hI-5gd" id="G1f-GL-Joy"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Paste" keyEquivalent="v" id="gVA-U4-sdL">
|
||||
<connections>
|
||||
<action selector="paste:" target="Ady-hI-5gd" id="UvS-8e-Qdg"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Paste and Match Style" keyEquivalent="V" id="WeT-3V-zwk">
|
||||
<modifierMask key="keyEquivalentModifierMask" option="YES" command="YES"/>
|
||||
<connections>
|
||||
<action selector="pasteAsPlainText:" target="Ady-hI-5gd" id="cEh-KX-wJQ"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Delete" id="pa3-QI-u2k">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="delete:" target="Ady-hI-5gd" id="0Mk-Ml-PaM"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Select All" keyEquivalent="a" id="Ruw-6m-B2m">
|
||||
<connections>
|
||||
<action selector="selectAll:" target="Ady-hI-5gd" id="VNm-Mi-diN"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem isSeparatorItem="YES" id="uyl-h8-XO2"/>
|
||||
<menuItem title="Find" id="4EN-yA-p0u">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<menu key="submenu" title="Find" id="1b7-l0-nxx">
|
||||
<items>
|
||||
<menuItem title="Find…" tag="1" keyEquivalent="f" id="Xz5-n4-O0W">
|
||||
<connections>
|
||||
<action selector="performFindPanelAction:" target="Ady-hI-5gd" id="cD7-Qs-BN4"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Find and Replace…" tag="12" keyEquivalent="f" id="YEy-JH-Tfz">
|
||||
<modifierMask key="keyEquivalentModifierMask" option="YES" command="YES"/>
|
||||
<connections>
|
||||
<action selector="performFindPanelAction:" target="Ady-hI-5gd" id="WD3-Gg-5AJ"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Find Next" tag="2" keyEquivalent="g" id="q09-fT-Sye">
|
||||
<connections>
|
||||
<action selector="performFindPanelAction:" target="Ady-hI-5gd" id="NDo-RZ-v9R"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Find Previous" tag="3" keyEquivalent="G" id="OwM-mh-QMV">
|
||||
<connections>
|
||||
<action selector="performFindPanelAction:" target="Ady-hI-5gd" id="HOh-sY-3ay"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Use Selection for Find" tag="7" keyEquivalent="e" id="buJ-ug-pKt">
|
||||
<connections>
|
||||
<action selector="performFindPanelAction:" target="Ady-hI-5gd" id="U76-nv-p5D"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Jump to Selection" keyEquivalent="j" id="S0p-oC-mLd">
|
||||
<connections>
|
||||
<action selector="centerSelectionInVisibleArea:" target="Ady-hI-5gd" id="IOG-6D-g5B"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
</items>
|
||||
</menu>
|
||||
</menuItem>
|
||||
<menuItem title="Spelling and Grammar" id="Dv1-io-Yv7">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<menu key="submenu" title="Spelling" id="3IN-sU-3Bg">
|
||||
<items>
|
||||
<menuItem title="Show Spelling and Grammar" keyEquivalent=":" id="HFo-cy-zxI">
|
||||
<connections>
|
||||
<action selector="showGuessPanel:" target="Ady-hI-5gd" id="vFj-Ks-hy3"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Check Document Now" keyEquivalent=";" id="hz2-CU-CR7">
|
||||
<connections>
|
||||
<action selector="checkSpelling:" target="Ady-hI-5gd" id="fz7-VC-reM"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem isSeparatorItem="YES" id="bNw-od-mp5"/>
|
||||
<menuItem title="Check Spelling While Typing" id="rbD-Rh-wIN">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="toggleContinuousSpellChecking:" target="Ady-hI-5gd" id="7w6-Qz-0kB"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Check Grammar With Spelling" id="mK6-2p-4JG">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="toggleGrammarChecking:" target="Ady-hI-5gd" id="muD-Qn-j4w"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Correct Spelling Automatically" id="78Y-hA-62v">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="toggleAutomaticSpellingCorrection:" target="Ady-hI-5gd" id="2lM-Qi-WAP"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
</items>
|
||||
</menu>
|
||||
</menuItem>
|
||||
<menuItem title="Substitutions" id="9ic-FL-obx">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<menu key="submenu" title="Substitutions" id="FeM-D8-WVr">
|
||||
<items>
|
||||
<menuItem title="Show Substitutions" id="z6F-FW-3nz">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="orderFrontSubstitutionsPanel:" target="Ady-hI-5gd" id="oku-mr-iSq"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem isSeparatorItem="YES" id="gPx-C9-uUO"/>
|
||||
<menuItem title="Smart Copy/Paste" id="9yt-4B-nSM">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="toggleSmartInsertDelete:" target="Ady-hI-5gd" id="3IJ-Se-DZD"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Smart Quotes" id="hQb-2v-fYv">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="toggleAutomaticQuoteSubstitution:" target="Ady-hI-5gd" id="ptq-xd-QOA"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Smart Dashes" id="rgM-f4-ycn">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="toggleAutomaticDashSubstitution:" target="Ady-hI-5gd" id="oCt-pO-9gS"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Smart Links" id="cwL-P1-jid">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="toggleAutomaticLinkDetection:" target="Ady-hI-5gd" id="Gip-E3-Fov"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Data Detectors" id="tRr-pd-1PS">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="toggleAutomaticDataDetection:" target="Ady-hI-5gd" id="R1I-Nq-Kbl"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Text Replacement" id="HFQ-gK-NFA">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="toggleAutomaticTextReplacement:" target="Ady-hI-5gd" id="DvP-Fe-Py6"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
</items>
|
||||
</menu>
|
||||
</menuItem>
|
||||
<menuItem title="Transformations" id="2oI-Rn-ZJC">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<menu key="submenu" title="Transformations" id="c8a-y6-VQd">
|
||||
<items>
|
||||
<menuItem title="Make Upper Case" id="vmV-6d-7jI">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="uppercaseWord:" target="Ady-hI-5gd" id="sPh-Tk-edu"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Make Lower Case" id="d9M-CD-aMd">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="lowercaseWord:" target="Ady-hI-5gd" id="iUZ-b5-hil"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Capitalize" id="UEZ-Bs-lqG">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="capitalizeWord:" target="Ady-hI-5gd" id="26H-TL-nsh"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
</items>
|
||||
</menu>
|
||||
</menuItem>
|
||||
<menuItem title="Speech" id="xrE-MZ-jX0">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<menu key="submenu" title="Speech" id="3rS-ZA-NoH">
|
||||
<items>
|
||||
<menuItem title="Start Speaking" id="Ynk-f8-cLZ">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="startSpeaking:" target="Ady-hI-5gd" id="654-Ng-kyl"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Stop Speaking" id="Oyz-dy-DGm">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="stopSpeaking:" target="Ady-hI-5gd" id="dX8-6p-jy9"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
</items>
|
||||
</menu>
|
||||
</menuItem>
|
||||
</items>
|
||||
</menu>
|
||||
</menuItem>
|
||||
<menuItem title="Format" id="jxT-CU-nIS">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<menu key="submenu" title="Format" id="GEO-Iw-cKr">
|
||||
<items>
|
||||
<menuItem title="Font" id="Gi5-1S-RQB">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<menu key="submenu" title="Font" systemMenu="font" id="aXa-aM-Jaq">
|
||||
<items>
|
||||
<menuItem title="Show Fonts" keyEquivalent="t" id="Q5e-8K-NDq">
|
||||
<connections>
|
||||
<action selector="orderFrontFontPanel:" target="YLy-65-1bz" id="WHr-nq-2xA"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Bold" tag="2" keyEquivalent="b" id="GB9-OM-e27">
|
||||
<connections>
|
||||
<action selector="addFontTrait:" target="YLy-65-1bz" id="hqk-hr-sYV"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Italic" tag="1" keyEquivalent="i" id="Vjx-xi-njq">
|
||||
<connections>
|
||||
<action selector="addFontTrait:" target="YLy-65-1bz" id="IHV-OB-c03"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Underline" keyEquivalent="u" id="WRG-CD-K1S">
|
||||
<connections>
|
||||
<action selector="underline:" target="Ady-hI-5gd" id="FYS-2b-JAY"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem isSeparatorItem="YES" id="5gT-KC-WSO"/>
|
||||
<menuItem title="Bigger" tag="3" keyEquivalent="+" id="Ptp-SP-VEL">
|
||||
<connections>
|
||||
<action selector="modifyFont:" target="YLy-65-1bz" id="Uc7-di-UnL"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Smaller" tag="4" keyEquivalent="-" id="i1d-Er-qST">
|
||||
<connections>
|
||||
<action selector="modifyFont:" target="YLy-65-1bz" id="HcX-Lf-eNd"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem isSeparatorItem="YES" id="kx3-Dk-x3B"/>
|
||||
<menuItem title="Kern" id="jBQ-r6-VK2">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<menu key="submenu" title="Kern" id="tlD-Oa-oAM">
|
||||
<items>
|
||||
<menuItem title="Use Default" id="GUa-eO-cwY">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="useStandardKerning:" target="Ady-hI-5gd" id="6dk-9l-Ckg"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Use None" id="cDB-IK-hbR">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="turnOffKerning:" target="Ady-hI-5gd" id="U8a-gz-Maa"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Tighten" id="46P-cB-AYj">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="tightenKerning:" target="Ady-hI-5gd" id="hr7-Nz-8ro"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Loosen" id="ogc-rX-tC1">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="loosenKerning:" target="Ady-hI-5gd" id="8i4-f9-FKE"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
</items>
|
||||
</menu>
|
||||
</menuItem>
|
||||
<menuItem title="Ligatures" id="o6e-r0-MWq">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<menu key="submenu" title="Ligatures" id="w0m-vy-SC9">
|
||||
<items>
|
||||
<menuItem title="Use Default" id="agt-UL-0e3">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="useStandardLigatures:" target="Ady-hI-5gd" id="7uR-wd-Dx6"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Use None" id="J7y-lM-qPV">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="turnOffLigatures:" target="Ady-hI-5gd" id="iX2-gA-Ilz"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Use All" id="xQD-1f-W4t">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="useAllLigatures:" target="Ady-hI-5gd" id="KcB-kA-TuK"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
</items>
|
||||
</menu>
|
||||
</menuItem>
|
||||
<menuItem title="Baseline" id="OaQ-X3-Vso">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<menu key="submenu" title="Baseline" id="ijk-EB-dga">
|
||||
<items>
|
||||
<menuItem title="Use Default" id="3Om-Ey-2VK">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="unscript:" target="Ady-hI-5gd" id="0vZ-95-Ywn"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Superscript" id="Rqc-34-cIF">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="superscript:" target="Ady-hI-5gd" id="3qV-fo-wpU"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Subscript" id="I0S-gh-46l">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="subscript:" target="Ady-hI-5gd" id="Q6W-4W-IGz"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Raise" id="2h7-ER-AoG">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="raiseBaseline:" target="Ady-hI-5gd" id="4sk-31-7Q9"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Lower" id="1tx-W0-xDw">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="lowerBaseline:" target="Ady-hI-5gd" id="OF1-bc-KW4"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
</items>
|
||||
</menu>
|
||||
</menuItem>
|
||||
<menuItem isSeparatorItem="YES" id="Ndw-q3-faq"/>
|
||||
<menuItem title="Show Colors" keyEquivalent="C" id="bgn-CT-cEk">
|
||||
<connections>
|
||||
<action selector="orderFrontColorPanel:" target="Ady-hI-5gd" id="mSX-Xz-DV3"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem isSeparatorItem="YES" id="iMs-zA-UFJ"/>
|
||||
<menuItem title="Copy Style" keyEquivalent="c" id="5Vv-lz-BsD">
|
||||
<modifierMask key="keyEquivalentModifierMask" option="YES" command="YES"/>
|
||||
<connections>
|
||||
<action selector="copyFont:" target="Ady-hI-5gd" id="GJO-xA-L4q"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Paste Style" keyEquivalent="v" id="vKC-jM-MkH">
|
||||
<modifierMask key="keyEquivalentModifierMask" option="YES" command="YES"/>
|
||||
<connections>
|
||||
<action selector="pasteFont:" target="Ady-hI-5gd" id="JfD-CL-leO"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
</items>
|
||||
</menu>
|
||||
</menuItem>
|
||||
<menuItem title="Text" id="Fal-I4-PZk">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<menu key="submenu" title="Text" id="d9c-me-L2H">
|
||||
<items>
|
||||
<menuItem title="Align Left" keyEquivalent="{" id="ZM1-6Q-yy1">
|
||||
<connections>
|
||||
<action selector="alignLeft:" target="Ady-hI-5gd" id="zUv-R1-uAa"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Center" keyEquivalent="|" id="VIY-Ag-zcb">
|
||||
<connections>
|
||||
<action selector="alignCenter:" target="Ady-hI-5gd" id="spX-mk-kcS"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Justify" id="J5U-5w-g23">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="alignJustified:" target="Ady-hI-5gd" id="ljL-7U-jND"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Align Right" keyEquivalent="}" id="wb2-vD-lq4">
|
||||
<connections>
|
||||
<action selector="alignRight:" target="Ady-hI-5gd" id="r48-bG-YeY"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem isSeparatorItem="YES" id="4s2-GY-VfK"/>
|
||||
<menuItem title="Writing Direction" id="H1b-Si-o9J">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<menu key="submenu" title="Writing Direction" id="8mr-sm-Yjd">
|
||||
<items>
|
||||
<menuItem title="Paragraph" enabled="NO" id="ZvO-Gk-QUH">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
</menuItem>
|
||||
<menuItem id="YGs-j5-SAR">
|
||||
<string key="title"> Default</string>
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="makeBaseWritingDirectionNatural:" target="Ady-hI-5gd" id="qtV-5e-UBP"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem id="Lbh-J2-qVU">
|
||||
<string key="title"> Left to Right</string>
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="makeBaseWritingDirectionLeftToRight:" target="Ady-hI-5gd" id="S0X-9S-QSf"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem id="jFq-tB-4Kx">
|
||||
<string key="title"> Right to Left</string>
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="makeBaseWritingDirectionRightToLeft:" target="Ady-hI-5gd" id="5fk-qB-AqJ"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem isSeparatorItem="YES" id="swp-gr-a21"/>
|
||||
<menuItem title="Selection" enabled="NO" id="cqv-fj-IhA">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
</menuItem>
|
||||
<menuItem id="Nop-cj-93Q">
|
||||
<string key="title"> Default</string>
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="makeTextWritingDirectionNatural:" target="Ady-hI-5gd" id="lPI-Se-ZHp"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem id="BgM-ve-c93">
|
||||
<string key="title"> Left to Right</string>
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="makeTextWritingDirectionLeftToRight:" target="Ady-hI-5gd" id="caW-Bv-w94"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem id="RB4-Sm-HuC">
|
||||
<string key="title"> Right to Left</string>
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="makeTextWritingDirectionRightToLeft:" target="Ady-hI-5gd" id="EXD-6r-ZUu"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
</items>
|
||||
</menu>
|
||||
</menuItem>
|
||||
<menuItem isSeparatorItem="YES" id="fKy-g9-1gm"/>
|
||||
<menuItem title="Show Ruler" id="vLm-3I-IUL">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="toggleRuler:" target="Ady-hI-5gd" id="FOx-HJ-KwY"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Copy Ruler" keyEquivalent="c" id="MkV-Pr-PK5">
|
||||
<modifierMask key="keyEquivalentModifierMask" control="YES" command="YES"/>
|
||||
<connections>
|
||||
<action selector="copyRuler:" target="Ady-hI-5gd" id="71i-fW-3W2"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Paste Ruler" keyEquivalent="v" id="LVM-kO-fVI">
|
||||
<modifierMask key="keyEquivalentModifierMask" control="YES" command="YES"/>
|
||||
<connections>
|
||||
<action selector="pasteRuler:" target="Ady-hI-5gd" id="cSh-wd-qM2"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
</items>
|
||||
</menu>
|
||||
</menuItem>
|
||||
</items>
|
||||
</menu>
|
||||
</menuItem>
|
||||
<menuItem title="View" id="H8h-7b-M4v">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<menu key="submenu" title="View" id="HyV-fh-RgO">
|
||||
<items>
|
||||
<menuItem title="Show Toolbar" keyEquivalent="t" id="snW-S8-Cw5">
|
||||
<modifierMask key="keyEquivalentModifierMask" option="YES" command="YES"/>
|
||||
<connections>
|
||||
<action selector="toggleToolbarShown:" target="Ady-hI-5gd" id="BXY-wc-z0C"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Customize Toolbar…" id="1UK-8n-QPP">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="runToolbarCustomizationPalette:" target="Ady-hI-5gd" id="pQI-g3-MTW"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem isSeparatorItem="YES" id="hB3-LF-h0Y"/>
|
||||
<menuItem title="Show Sidebar" keyEquivalent="s" id="kIP-vf-haE">
|
||||
<modifierMask key="keyEquivalentModifierMask" control="YES" command="YES"/>
|
||||
<connections>
|
||||
<action selector="toggleSidebar:" target="Ady-hI-5gd" id="iwa-gc-5KM"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Enter Full Screen" keyEquivalent="f" id="4J7-dP-txa">
|
||||
<modifierMask key="keyEquivalentModifierMask" control="YES" command="YES"/>
|
||||
<connections>
|
||||
<action selector="toggleFullScreen:" target="Ady-hI-5gd" id="dU3-MA-1Rq"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
</items>
|
||||
</menu>
|
||||
</menuItem>
|
||||
<menuItem title="Window" id="aUF-d1-5bR">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<menu key="submenu" title="Window" systemMenu="window" id="Td7-aD-5lo">
|
||||
<items>
|
||||
<menuItem title="Minimize" keyEquivalent="m" id="OY7-WF-poV">
|
||||
<connections>
|
||||
<action selector="performMiniaturize:" target="Ady-hI-5gd" id="VwT-WD-YPe"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Zoom" id="R4o-n2-Eq4">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="performZoom:" target="Ady-hI-5gd" id="DIl-cC-cCs"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem isSeparatorItem="YES" id="eu3-7i-yIM"/>
|
||||
<menuItem title="Bring All to Front" id="LE2-aR-0XJ">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="arrangeInFront:" target="Ady-hI-5gd" id="DRN-fu-gQh"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
</items>
|
||||
</menu>
|
||||
</menuItem>
|
||||
<menuItem title="Help" id="wpr-3q-Mcd">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<menu key="submenu" title="Help" systemMenu="help" id="F2S-fz-NVQ">
|
||||
<items>
|
||||
<menuItem title="Gemini Help" keyEquivalent="?" id="FKE-Sm-Kum">
|
||||
<connections>
|
||||
<action selector="showHelp:" target="Ady-hI-5gd" id="y7X-2Q-9no"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
</items>
|
||||
</menu>
|
||||
</menuItem>
|
||||
</items>
|
||||
</menu>
|
||||
<connections>
|
||||
<outlet property="delegate" destination="Voe-Tx-rLC" id="PrD-fu-P6m"/>
|
||||
</connections>
|
||||
</application>
|
||||
<customObject id="Voe-Tx-rLC" customClass="AppDelegate" customModuleProvider="target"/>
|
||||
<customObject id="YLy-65-1bz" customClass="NSFontManager"/>
|
||||
<customObject id="Ady-hI-5gd" userLabel="First Responder" customClass="NSResponder" sceneMemberID="firstResponder"/>
|
||||
</objects>
|
||||
<point key="canvasLocation" x="75" y="0.0"/>
|
||||
</scene>
|
||||
</scenes>
|
||||
</document>
|
|
@ -0,0 +1,165 @@
|
|||
//
|
||||
// BrowserWindowController.swift
|
||||
// Gemini
|
||||
//
|
||||
// Created by Shadowfacts on 7/15/20.
|
||||
//
|
||||
|
||||
import Cocoa
|
||||
import SwiftUI
|
||||
import Combine
|
||||
import BrowserCore
|
||||
|
||||
class BrowserWindowController: NSWindowController {
|
||||
|
||||
@IBOutlet weak var toolbar: NSToolbar!
|
||||
|
||||
private var locationTextField: NSTextField?
|
||||
|
||||
private var urlUpdater: Cancellable?
|
||||
|
||||
let navigator = NavigationManager(url: AppDelegate.homePage)
|
||||
|
||||
convenience init() {
|
||||
self.init(windowNibName: "BrowserWindowController")
|
||||
}
|
||||
|
||||
override func windowDidLoad() {
|
||||
super.windowDidLoad()
|
||||
|
||||
contentViewController = NSHostingController(rootView: BrowserView(navigator: navigator))
|
||||
|
||||
urlUpdater = navigator.$currentURL.sink(receiveValue: self.currentURLChanged(_:))
|
||||
}
|
||||
|
||||
private func currentURLChanged(_ newValue: URL) {
|
||||
locationTextField?.stringValue = newValue.absoluteString
|
||||
|
||||
window?.title = newValue.absoluteString
|
||||
}
|
||||
|
||||
override func newWindowForTab(_ sender: Any?) {
|
||||
(NSApp.delegate as! AppDelegate).createNewWindowTab(attachedTo: window!)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
extension NSToolbarItem.Identifier {
|
||||
static let locationField = NSToolbarItem.Identifier("Gemini.locationField")
|
||||
static let goBack = NSToolbarItem.Identifier("Gemini.goBack")
|
||||
static let goForward = NSToolbarItem.Identifier("Gemini.goForward")
|
||||
}
|
||||
|
||||
extension BrowserWindowController: NSToolbarDelegate {
|
||||
func toolbarAllowedItemIdentifiers(_ toolbar: NSToolbar) -> [NSToolbarItem.Identifier] {
|
||||
return [
|
||||
.space,
|
||||
.flexibleSpace,
|
||||
.locationField,
|
||||
.goBack,
|
||||
.goForward
|
||||
]
|
||||
}
|
||||
|
||||
func toolbarDefaultItemIdentifiers(_ toolbar: NSToolbar) -> [NSToolbarItem.Identifier] {
|
||||
return [
|
||||
.goBack,
|
||||
.goForward,
|
||||
.flexibleSpace,
|
||||
.locationField,
|
||||
.flexibleSpace,
|
||||
]
|
||||
}
|
||||
|
||||
func toolbar(_ toolbar: NSToolbar, itemForItemIdentifier itemIdentifier: NSToolbarItem.Identifier, willBeInsertedIntoToolbar flag: Bool) -> NSToolbarItem? {
|
||||
if itemIdentifier == .locationField {
|
||||
return createLocationFieldToolbarItem()
|
||||
} else if itemIdentifier == .goBack {
|
||||
return createBackToolbarItem()
|
||||
} else if itemIdentifier == .goForward {
|
||||
return createForwardToolbarItem()
|
||||
}
|
||||
return NSToolbarItem(itemIdentifier: itemIdentifier)
|
||||
}
|
||||
|
||||
private func createLocationFieldToolbarItem() -> NSToolbarItem {
|
||||
let item = NSToolbarItem(itemIdentifier: .locationField)
|
||||
item.label = "Location"
|
||||
item.paletteLabel = "Location"
|
||||
let textField = NSTextField(string: navigator.currentURL.absoluteString)
|
||||
textField.delegate = self
|
||||
NSLayoutConstraint.activate([
|
||||
textField.heightAnchor.constraint(equalToConstant: 22),
|
||||
textField.widthAnchor.constraint(lessThanOrEqualToConstant: 500),
|
||||
textField.widthAnchor.constraint(greaterThanOrEqualToConstant: 250)
|
||||
])
|
||||
locationTextField = textField
|
||||
item.view = textField
|
||||
return item
|
||||
}
|
||||
|
||||
private func createBackToolbarItem() -> NSToolbarItem {
|
||||
let item = NSToolbarItem(itemIdentifier: .goBack)
|
||||
if #available(macOS 10.16, *) {
|
||||
item.image = NSImage(systemSymbolName: "chevron.left", accessibilityDescription: "Go Back")
|
||||
} else {
|
||||
item.image = NSImage(named: NSImage.goBackTemplateName)
|
||||
}
|
||||
item.label = "Go Back"
|
||||
item.paletteLabel = "Go Back"
|
||||
item.toolTip = "Go to the previous page"
|
||||
item.target = navigator
|
||||
item.action = #selector(NavigationManager.back)
|
||||
item.isBordered = true
|
||||
if #available(macOS 10.16, *) {
|
||||
item.isNavigational = true
|
||||
}
|
||||
return item
|
||||
}
|
||||
|
||||
private func createForwardToolbarItem() -> NSToolbarItem {
|
||||
let item = NSToolbarItem(itemIdentifier: .goForward)
|
||||
if #available(macOS 10.16, *) {
|
||||
item.image = NSImage(systemSymbolName: "chevron.right", accessibilityDescription: "Go Forward")
|
||||
} else {
|
||||
item.image = NSImage(named: NSImage.goForwardTemplateName)
|
||||
}
|
||||
item.label = "Go Forward"
|
||||
item.paletteLabel = "Go Forward"
|
||||
item.toolTip = "Go to the next page"
|
||||
item.target = navigator
|
||||
item.action = #selector(NavigationManager.forward)
|
||||
item.isBordered = true
|
||||
if #available(macOS 10.16, *) {
|
||||
item.isNavigational = true
|
||||
}
|
||||
return item
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
extension NavigationManager: NSToolbarItemValidation {
|
||||
public func validateToolbarItem(_ item: NSToolbarItem) -> Bool {
|
||||
if item.itemIdentifier == .goBack {
|
||||
return !backStack.isEmpty
|
||||
} else if item.itemIdentifier == .goForward {
|
||||
return !forwardStack.isEmpty
|
||||
} else {
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extension BrowserWindowController: NSTextFieldDelegate {
|
||||
func controlTextDidEndEditing(_ obj: Notification) {
|
||||
guard let textField = locationTextField else { return }
|
||||
guard let newURL = URL(string: textField.stringValue) else {
|
||||
let alert = NSAlert()
|
||||
alert.alertStyle = .warning
|
||||
alert.messageText = "You specified a malformed URL"
|
||||
alert.addButton(withTitle: "OK")
|
||||
return
|
||||
}
|
||||
navigator.changeURL(newURL)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,38 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="17132" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" customObjectInstantitationMethod="direct">
|
||||
<dependencies>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="17132"/>
|
||||
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
||||
</dependencies>
|
||||
<objects>
|
||||
<customObject id="-2" userLabel="File's Owner" customClass="BrowserWindowController" customModule="Gemini" customModuleProvider="target">
|
||||
<connections>
|
||||
<outlet property="toolbar" destination="9ug-B7-edO" id="b5B-iv-AvC"/>
|
||||
<outlet property="window" destination="F0z-JX-Cv5" id="gIp-Ho-8D9"/>
|
||||
</connections>
|
||||
</customObject>
|
||||
<customObject id="-1" userLabel="First Responder" customClass="FirstResponder"/>
|
||||
<customObject id="-3" userLabel="Application" customClass="NSObject"/>
|
||||
<window title="Window" allowsToolTipsWhenApplicationIsInactive="NO" autorecalculatesKeyViewLoop="NO" releasedWhenClosed="NO" frameAutosaveName="BrowserWindow" animationBehavior="default" tabbingIdentifier="BrowserWindow" tabbingMode="preferred" toolbarStyle="unified" titleVisibility="hidden" id="F0z-JX-Cv5">
|
||||
<windowStyleMask key="styleMask" titled="YES" closable="YES" miniaturizable="YES" resizable="YES" fullSizeContentView="YES"/>
|
||||
<windowPositionMask key="initialPositionMask" leftStrut="YES" rightStrut="YES" topStrut="YES" bottomStrut="YES"/>
|
||||
<rect key="contentRect" x="196" y="240" width="480" height="270"/>
|
||||
<rect key="screenRect" x="0.0" y="0.0" width="2560" height="1415"/>
|
||||
<view key="contentView" id="se5-gp-TjO">
|
||||
<rect key="frame" x="0.0" y="0.0" width="480" height="270"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
</view>
|
||||
<toolbar key="toolbar" implicitIdentifier="F9FE9EDF-BA47-49F1-A430-76A94FA9E3E3" displayMode="iconOnly" sizeMode="regular" id="9ug-B7-edO">
|
||||
<allowedToolbarItems/>
|
||||
<defaultToolbarItems/>
|
||||
<connections>
|
||||
<outlet property="delegate" destination="-2" id="o6y-uG-vE9"/>
|
||||
</connections>
|
||||
</toolbar>
|
||||
<connections>
|
||||
<outlet property="delegate" destination="-2" id="0bl-1N-AYu"/>
|
||||
</connections>
|
||||
<point key="canvasLocation" x="140" y="144"/>
|
||||
</window>
|
||||
</objects>
|
||||
</document>
|
|
@ -6,84 +6,14 @@
|
|||
//
|
||||
|
||||
import SwiftUI
|
||||
import GeminiFormat
|
||||
import GeminiRenderer
|
||||
import GeminiProtocol
|
||||
import BrowserCore
|
||||
|
||||
struct ContentView: View {
|
||||
let navigator: NavigationManager
|
||||
@State var task: GeminiDataTask?
|
||||
@State var document: Document?
|
||||
@State var errorMessage: String?
|
||||
|
||||
var body: some View {
|
||||
VStack {
|
||||
HStack {
|
||||
Button(action: navigator.back) {
|
||||
Image(systemName: "chevron.left")
|
||||
}.disabled(navigator.backStack.isEmpty)
|
||||
Button(action: navigator.forward) {
|
||||
Image(systemName: "chevron.right")
|
||||
}.disabled(navigator.forwardStack.isEmpty)
|
||||
TextField("URL", text: Binding<String>(get: {
|
||||
self.navigator.currentURL.absoluteString
|
||||
}, set: { (newValue) in
|
||||
self.navigator.currentURL = URL(string: newValue)!
|
||||
}))
|
||||
}.padding([.leading, .trailing])
|
||||
mainView.frame(maxWidth: .infinity, maxHeight: .infinity)
|
||||
}
|
||||
BrowserView(navigator: navigator)
|
||||
.frame(minWidth: 480, maxWidth: .infinity, minHeight: 300, maxHeight: .infinity)
|
||||
.onReceive(navigator.$currentURL, perform: self.urlChanged)
|
||||
}
|
||||
|
||||
@ViewBuilder
|
||||
private var mainView: some View {
|
||||
if let document = document {
|
||||
DocumentView(document: document, changeURL: navigator.changeURL)
|
||||
} else if let errorMessage = errorMessage {
|
||||
VStack {
|
||||
Text("An error occurred")
|
||||
.font(.headline)
|
||||
Text(errorMessage)
|
||||
}
|
||||
} else {
|
||||
loadingView
|
||||
.onAppear(perform: self.loadDocument)
|
||||
}
|
||||
}
|
||||
|
||||
@ViewBuilder
|
||||
private var loadingView: some View {
|
||||
if #available(macOS 10.16, iOS 14.0, *) {
|
||||
ProgressView("Loading...")
|
||||
} else {
|
||||
Text("Loading...")
|
||||
}
|
||||
}
|
||||
|
||||
private func loadDocument() {
|
||||
let url = navigator.currentURL
|
||||
task = try! GeminiDataTask(url: url, completion: { (response) in
|
||||
switch response {
|
||||
case let .failure(error):
|
||||
self.errorMessage = error.localizedDescription
|
||||
case let .success(response):
|
||||
guard let text = response.bodyText else {
|
||||
self.errorMessage = "Response had no body text"
|
||||
return
|
||||
}
|
||||
self.document = GeminiParser.parse(text: text, baseURL: url)
|
||||
}
|
||||
self.task = nil
|
||||
})
|
||||
task!.resume()
|
||||
}
|
||||
|
||||
private func urlChanged(_ newValue: URL) {
|
||||
self.task = nil
|
||||
self.document = nil
|
||||
self.errorMessage = nil
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -2,6 +2,8 @@
|
|||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>NSMainNibFile</key>
|
||||
<string>MainMenu</string>
|
||||
<key>CFBundleDevelopmentRegion</key>
|
||||
<string>$(DEVELOPMENT_LANGUAGE)</string>
|
||||
<key>CFBundleExecutable</key>
|
||||
|
@ -22,8 +24,6 @@
|
|||
<string>1</string>
|
||||
<key>LSMinimumSystemVersion</key>
|
||||
<string>$(MACOSX_DEPLOYMENT_TARGET)</string>
|
||||
<key>NSMainStoryboardFile</key>
|
||||
<string>Main</string>
|
||||
<key>NSPrincipalClass</key>
|
||||
<string>NSApplication</string>
|
||||
</dict>
|
||||
|
|
|
@ -0,0 +1,423 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="17132" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" customObjectInstantitationMethod="direct">
|
||||
<dependencies>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="17132"/>
|
||||
</dependencies>
|
||||
<objects>
|
||||
<customObject id="-2" userLabel="File's Owner" customClass="NSApplication">
|
||||
<connections>
|
||||
<outlet property="delegate" destination="Voe-Tx-rLC" id="GzC-gU-4Uq"/>
|
||||
</connections>
|
||||
</customObject>
|
||||
<customObject id="-1" userLabel="First Responder" customClass="FirstResponder"/>
|
||||
<customObject id="-3" userLabel="Application" customClass="NSObject"/>
|
||||
<customObject id="Voe-Tx-rLC" customClass="AppDelegate" customModule="Gemini" customModuleProvider="target"/>
|
||||
<customObject id="YLy-65-1bz" customClass="NSFontManager"/>
|
||||
<menu title="Main Menu" systemMenu="main" id="AYu-sK-qS6">
|
||||
<items>
|
||||
<menuItem title="Gemini" id="1Xt-HY-uBw">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<menu key="submenu" title="Gemini" systemMenu="apple" id="uQy-DD-JDr">
|
||||
<items>
|
||||
<menuItem title="About Gemini" id="5kV-Vb-QxS">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="orderFrontStandardAboutPanel:" target="-1" id="Exp-CZ-Vem"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem isSeparatorItem="YES" id="VOq-y0-SEH"/>
|
||||
<menuItem title="Preferences…" keyEquivalent="," id="BOF-NM-1cW"/>
|
||||
<menuItem isSeparatorItem="YES" id="wFC-TO-SCJ"/>
|
||||
<menuItem title="Services" id="NMo-om-nkz">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<menu key="submenu" title="Services" systemMenu="services" id="hz9-B4-Xy5"/>
|
||||
</menuItem>
|
||||
<menuItem isSeparatorItem="YES" id="4je-JR-u6R"/>
|
||||
<menuItem title="Hide Gemini" keyEquivalent="h" id="Olw-nP-bQN">
|
||||
<connections>
|
||||
<action selector="hide:" target="-1" id="PnN-Uc-m68"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Hide Others" keyEquivalent="h" id="Vdr-fp-XzO">
|
||||
<modifierMask key="keyEquivalentModifierMask" option="YES" command="YES"/>
|
||||
<connections>
|
||||
<action selector="hideOtherApplications:" target="-1" id="VT4-aY-XCT"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Show All" id="Kd2-mp-pUS">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="unhideAllApplications:" target="-1" id="Dhg-Le-xox"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem isSeparatorItem="YES" id="kCx-OE-vgT"/>
|
||||
<menuItem title="Quit Gemini" keyEquivalent="q" id="4sb-4s-VLi">
|
||||
<connections>
|
||||
<action selector="terminate:" target="-1" id="Te7-pn-YzF"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
</items>
|
||||
</menu>
|
||||
</menuItem>
|
||||
<menuItem title="File" id="dMs-cI-mzQ">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<menu key="submenu" title="File" id="bib-Uj-vzu">
|
||||
<items>
|
||||
<menuItem title="New" keyEquivalent="n" id="Was-JA-tGl">
|
||||
<connections>
|
||||
<action selector="newDocument:" target="-1" id="4Si-XN-c54"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="New Tab" keyEquivalent="t" id="9AK-Fk-TxU">
|
||||
<connections>
|
||||
<action selector="newTab:" target="Voe-Tx-rLC" id="JyK-8N-xQT"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Open…" keyEquivalent="o" id="IAo-SY-fd9">
|
||||
<connections>
|
||||
<action selector="openDocument:" target="-1" id="bVn-NM-KNZ"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Open Recent" id="tXI-mr-wws">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<menu key="submenu" title="Open Recent" systemMenu="recentDocuments" id="oas-Oc-fiZ">
|
||||
<items>
|
||||
<menuItem title="Clear Menu" id="vNY-rz-j42">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="clearRecentDocuments:" target="-1" id="Daa-9d-B3U"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
</items>
|
||||
</menu>
|
||||
</menuItem>
|
||||
<menuItem isSeparatorItem="YES" id="m54-Is-iLE"/>
|
||||
<menuItem title="Close" keyEquivalent="w" id="DVo-aG-piG">
|
||||
<connections>
|
||||
<action selector="performClose:" target="-1" id="HmO-Ls-i7Q"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Save…" keyEquivalent="s" id="pxx-59-PXV">
|
||||
<connections>
|
||||
<action selector="saveDocument:" target="-1" id="teZ-XB-qJY"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Save As…" keyEquivalent="S" id="Bw7-FT-i3A">
|
||||
<connections>
|
||||
<action selector="saveDocumentAs:" target="-1" id="mDf-zr-I0C"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Revert to Saved" id="KaW-ft-85H">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="revertDocumentToSaved:" target="-1" id="iJ3-Pv-kwq"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem isSeparatorItem="YES" id="aJh-i4-bef"/>
|
||||
<menuItem title="Page Setup…" keyEquivalent="P" id="qIS-W8-SiK">
|
||||
<modifierMask key="keyEquivalentModifierMask" shift="YES" command="YES"/>
|
||||
<connections>
|
||||
<action selector="runPageLayout:" target="-1" id="Din-rz-gC5"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Print…" keyEquivalent="p" id="aTl-1u-JFS">
|
||||
<connections>
|
||||
<action selector="print:" target="-1" id="qaZ-4w-aoO"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
</items>
|
||||
</menu>
|
||||
</menuItem>
|
||||
<menuItem title="Edit" id="5QF-Oa-p0T">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<menu key="submenu" title="Edit" id="W48-6f-4Dl">
|
||||
<items>
|
||||
<menuItem title="Undo" keyEquivalent="z" id="dRJ-4n-Yzg">
|
||||
<connections>
|
||||
<action selector="undo:" target="-1" id="M6e-cu-g7V"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Redo" keyEquivalent="Z" id="6dh-zS-Vam">
|
||||
<connections>
|
||||
<action selector="redo:" target="-1" id="oIA-Rs-6OD"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem isSeparatorItem="YES" id="WRV-NI-Exz"/>
|
||||
<menuItem title="Cut" keyEquivalent="x" id="uRl-iY-unG">
|
||||
<connections>
|
||||
<action selector="cut:" target="-1" id="YJe-68-I9s"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Copy" keyEquivalent="c" id="x3v-GG-iWU">
|
||||
<connections>
|
||||
<action selector="copy:" target="-1" id="G1f-GL-Joy"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Paste" keyEquivalent="v" id="gVA-U4-sdL">
|
||||
<connections>
|
||||
<action selector="paste:" target="-1" id="UvS-8e-Qdg"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Paste and Match Style" keyEquivalent="V" id="WeT-3V-zwk">
|
||||
<modifierMask key="keyEquivalentModifierMask" option="YES" command="YES"/>
|
||||
<connections>
|
||||
<action selector="pasteAsPlainText:" target="-1" id="cEh-KX-wJQ"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Delete" id="pa3-QI-u2k">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="delete:" target="-1" id="0Mk-Ml-PaM"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Select All" keyEquivalent="a" id="Ruw-6m-B2m">
|
||||
<connections>
|
||||
<action selector="selectAll:" target="-1" id="VNm-Mi-diN"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem isSeparatorItem="YES" id="uyl-h8-XO2"/>
|
||||
<menuItem title="Find" id="4EN-yA-p0u">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<menu key="submenu" title="Find" id="1b7-l0-nxx">
|
||||
<items>
|
||||
<menuItem title="Find…" tag="1" keyEquivalent="f" id="Xz5-n4-O0W">
|
||||
<connections>
|
||||
<action selector="performFindPanelAction:" target="-1" id="cD7-Qs-BN4"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Find and Replace…" tag="12" keyEquivalent="f" id="YEy-JH-Tfz">
|
||||
<modifierMask key="keyEquivalentModifierMask" option="YES" command="YES"/>
|
||||
<connections>
|
||||
<action selector="performFindPanelAction:" target="-1" id="WD3-Gg-5AJ"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Find Next" tag="2" keyEquivalent="g" id="q09-fT-Sye">
|
||||
<connections>
|
||||
<action selector="performFindPanelAction:" target="-1" id="NDo-RZ-v9R"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Find Previous" tag="3" keyEquivalent="G" id="OwM-mh-QMV">
|
||||
<connections>
|
||||
<action selector="performFindPanelAction:" target="-1" id="HOh-sY-3ay"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Use Selection for Find" tag="7" keyEquivalent="e" id="buJ-ug-pKt">
|
||||
<connections>
|
||||
<action selector="performFindPanelAction:" target="-1" id="U76-nv-p5D"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Jump to Selection" keyEquivalent="j" id="S0p-oC-mLd">
|
||||
<connections>
|
||||
<action selector="centerSelectionInVisibleArea:" target="-1" id="IOG-6D-g5B"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
</items>
|
||||
</menu>
|
||||
</menuItem>
|
||||
<menuItem title="Spelling and Grammar" id="Dv1-io-Yv7">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<menu key="submenu" title="Spelling" id="3IN-sU-3Bg">
|
||||
<items>
|
||||
<menuItem title="Show Spelling and Grammar" keyEquivalent=":" id="HFo-cy-zxI">
|
||||
<connections>
|
||||
<action selector="showGuessPanel:" target="-1" id="vFj-Ks-hy3"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Check Document Now" keyEquivalent=";" id="hz2-CU-CR7">
|
||||
<connections>
|
||||
<action selector="checkSpelling:" target="-1" id="fz7-VC-reM"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem isSeparatorItem="YES" id="bNw-od-mp5"/>
|
||||
<menuItem title="Check Spelling While Typing" id="rbD-Rh-wIN">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="toggleContinuousSpellChecking:" target="-1" id="7w6-Qz-0kB"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Check Grammar With Spelling" id="mK6-2p-4JG">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="toggleGrammarChecking:" target="-1" id="muD-Qn-j4w"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Correct Spelling Automatically" id="78Y-hA-62v">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="toggleAutomaticSpellingCorrection:" target="-1" id="2lM-Qi-WAP"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
</items>
|
||||
</menu>
|
||||
</menuItem>
|
||||
<menuItem title="Substitutions" id="9ic-FL-obx">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<menu key="submenu" title="Substitutions" id="FeM-D8-WVr">
|
||||
<items>
|
||||
<menuItem title="Show Substitutions" id="z6F-FW-3nz">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="orderFrontSubstitutionsPanel:" target="-1" id="oku-mr-iSq"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem isSeparatorItem="YES" id="gPx-C9-uUO"/>
|
||||
<menuItem title="Smart Copy/Paste" id="9yt-4B-nSM">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="toggleSmartInsertDelete:" target="-1" id="3IJ-Se-DZD"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Smart Quotes" id="hQb-2v-fYv">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="toggleAutomaticQuoteSubstitution:" target="-1" id="ptq-xd-QOA"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Smart Dashes" id="rgM-f4-ycn">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="toggleAutomaticDashSubstitution:" target="-1" id="oCt-pO-9gS"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Smart Links" id="cwL-P1-jid">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="toggleAutomaticLinkDetection:" target="-1" id="Gip-E3-Fov"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Data Detectors" id="tRr-pd-1PS">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="toggleAutomaticDataDetection:" target="-1" id="R1I-Nq-Kbl"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Text Replacement" id="HFQ-gK-NFA">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="toggleAutomaticTextReplacement:" target="-1" id="DvP-Fe-Py6"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
</items>
|
||||
</menu>
|
||||
</menuItem>
|
||||
<menuItem title="Transformations" id="2oI-Rn-ZJC">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<menu key="submenu" title="Transformations" id="c8a-y6-VQd">
|
||||
<items>
|
||||
<menuItem title="Make Upper Case" id="vmV-6d-7jI">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="uppercaseWord:" target="-1" id="sPh-Tk-edu"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Make Lower Case" id="d9M-CD-aMd">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="lowercaseWord:" target="-1" id="iUZ-b5-hil"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Capitalize" id="UEZ-Bs-lqG">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="capitalizeWord:" target="-1" id="26H-TL-nsh"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
</items>
|
||||
</menu>
|
||||
</menuItem>
|
||||
<menuItem title="Speech" id="xrE-MZ-jX0">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<menu key="submenu" title="Speech" id="3rS-ZA-NoH">
|
||||
<items>
|
||||
<menuItem title="Start Speaking" id="Ynk-f8-cLZ">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="startSpeaking:" target="-1" id="654-Ng-kyl"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Stop Speaking" id="Oyz-dy-DGm">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="stopSpeaking:" target="-1" id="dX8-6p-jy9"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
</items>
|
||||
</menu>
|
||||
</menuItem>
|
||||
</items>
|
||||
</menu>
|
||||
</menuItem>
|
||||
<menuItem title="View" id="H8h-7b-M4v">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<menu key="submenu" title="View" id="HyV-fh-RgO">
|
||||
<items>
|
||||
<menuItem title="Show Toolbar" keyEquivalent="t" id="snW-S8-Cw5">
|
||||
<modifierMask key="keyEquivalentModifierMask" option="YES" command="YES"/>
|
||||
<connections>
|
||||
<action selector="toggleToolbarShown:" target="-1" id="BXY-wc-z0C"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Customize Toolbar…" id="1UK-8n-QPP">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="runToolbarCustomizationPalette:" target="-1" id="pQI-g3-MTW"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem isSeparatorItem="YES" id="hB3-LF-h0Y"/>
|
||||
<menuItem title="Show Sidebar" keyEquivalent="s" id="kIP-vf-haE">
|
||||
<modifierMask key="keyEquivalentModifierMask" control="YES" command="YES"/>
|
||||
<connections>
|
||||
<action selector="toggleSidebar:" target="-1" id="iwa-gc-5KM"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Enter Full Screen" keyEquivalent="f" id="4J7-dP-txa">
|
||||
<modifierMask key="keyEquivalentModifierMask" control="YES" command="YES"/>
|
||||
<connections>
|
||||
<action selector="toggleFullScreen:" target="-1" id="dU3-MA-1Rq"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
</items>
|
||||
</menu>
|
||||
</menuItem>
|
||||
<menuItem title="Window" id="aUF-d1-5bR">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<menu key="submenu" title="Window" systemMenu="window" id="Td7-aD-5lo">
|
||||
<items>
|
||||
<menuItem title="Minimize" keyEquivalent="m" id="OY7-WF-poV">
|
||||
<connections>
|
||||
<action selector="performMiniaturize:" target="-1" id="VwT-WD-YPe"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Zoom" id="R4o-n2-Eq4">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="performZoom:" target="-1" id="DIl-cC-cCs"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem isSeparatorItem="YES" id="eu3-7i-yIM"/>
|
||||
<menuItem title="Bring All to Front" id="LE2-aR-0XJ">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="arrangeInFront:" target="-1" id="DRN-fu-gQh"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
</items>
|
||||
</menu>
|
||||
</menuItem>
|
||||
<menuItem title="Help" id="wpr-3q-Mcd">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<menu key="submenu" title="Help" systemMenu="help" id="F2S-fz-NVQ">
|
||||
<items>
|
||||
<menuItem title="Gemini Help" keyEquivalent="?" id="FKE-Sm-Kum">
|
||||
<connections>
|
||||
<action selector="showHelp:" target="-1" id="y7X-2Q-9no"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
</items>
|
||||
</menu>
|
||||
</menuItem>
|
||||
</items>
|
||||
<point key="canvasLocation" x="141" y="154"/>
|
||||
</menu>
|
||||
</objects>
|
||||
</document>
|
|
@ -1,38 +0,0 @@
|
|||
//
|
||||
// NavigationManager.swift
|
||||
// Gemini
|
||||
//
|
||||
// Created by Shadowfacts on 7/14/20.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
class NavigationManager: ObservableObject {
|
||||
|
||||
@Published var currentURL: URL
|
||||
@Published var backStack = [URL]()
|
||||
@Published var forwardStack = [URL]()
|
||||
|
||||
init(url: URL) {
|
||||
self.currentURL = url
|
||||
}
|
||||
|
||||
func changeURL(_ url: URL) {
|
||||
backStack.append(currentURL)
|
||||
currentURL = url
|
||||
forwardStack = []
|
||||
}
|
||||
|
||||
func back() {
|
||||
guard !backStack.isEmpty else { return }
|
||||
forwardStack.insert(currentURL, at: 0)
|
||||
currentURL = backStack.removeLast()
|
||||
}
|
||||
|
||||
func forward() {
|
||||
guard !forwardStack.isEmpty else { return }
|
||||
backStack.append(currentURL)
|
||||
currentURL = forwardStack.removeFirst()
|
||||
}
|
||||
|
||||
}
|
|
@ -32,7 +32,7 @@ public struct GeminiResponse {
|
|||
parameters[parts[0].lowercased()] = parts[1]
|
||||
}
|
||||
}
|
||||
@available(macOS 10.16, *)
|
||||
@available(macOS 10.16, iOS 14.0, *)
|
||||
public var utiType: UTType? {
|
||||
guard let mimeType = mimeType else { return nil }
|
||||
return UTType.types(tag: mimeType, tagClass: .mimeType, conformingTo: nil).first
|
||||
|
|
|
@ -35,15 +35,15 @@ public extension GeminiResponseHeader {
|
|||
case certificateNotValid = 62
|
||||
|
||||
// Status type helpers
|
||||
var isInput: Bool { rawValue / 10 == 1 }
|
||||
var isSuccess: Bool { rawValue / 10 == 2 }
|
||||
var isRedirect: Bool { rawValue / 10 == 3 }
|
||||
var isTemporaryFailure: Bool { rawValue / 10 == 4 }
|
||||
var isPermanentFailure: Bool { rawValue / 10 == 5 }
|
||||
var isClientCertificateRequired: Bool { rawValue / 10 == 6 }
|
||||
public var isInput: Bool { rawValue / 10 == 1 }
|
||||
public var isSuccess: Bool { rawValue / 10 == 2 }
|
||||
public var isRedirect: Bool { rawValue / 10 == 3 }
|
||||
public var isTemporaryFailure: Bool { rawValue / 10 == 4 }
|
||||
public var isPermanentFailure: Bool { rawValue / 10 == 5 }
|
||||
public var isClientCertificateRequired: Bool { rawValue / 10 == 6 }
|
||||
|
||||
// Other helpers
|
||||
var isFailure: Bool { isTemporaryFailure || isPermanentFailure }
|
||||
public var isFailure: Bool { isTemporaryFailure || isPermanentFailure }
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -25,7 +25,7 @@ public struct DocumentView: View {
|
|||
ForEach(blocks.indices) { (index) in
|
||||
RenderingBlockView(block: blocks[index], changeURL: changeURL)
|
||||
}
|
||||
}.padding()
|
||||
}.padding([.leading, .trailing, .bottom])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,6 +11,7 @@ import GeminiFormat
|
|||
struct RenderingBlockView: View {
|
||||
let block: RenderingBlock
|
||||
let changeURL: ((URL) -> Void)?
|
||||
@State var hovering = false
|
||||
|
||||
init(block: RenderingBlock, changeURL: ((URL) -> Void)? = nil) {
|
||||
self.block = block
|
||||
|
@ -21,48 +22,89 @@ struct RenderingBlockView: View {
|
|||
var body: some View {
|
||||
switch block {
|
||||
case let .text(text):
|
||||
self.text(text)
|
||||
case let .link(url, text: linkText):
|
||||
self.link(url, text: linkText)
|
||||
case let .preformatted(text, alt: _):
|
||||
preformatted(text)
|
||||
case let .heading(text, level: level):
|
||||
heading(text, level: level)
|
||||
case let .unorderedListItem(text):
|
||||
unorderedListItem(text)
|
||||
case let .quote(text):
|
||||
quote(text)
|
||||
}
|
||||
}
|
||||
|
||||
private func text(_ text: String) -> some View {
|
||||
Text(text)
|
||||
.font(.documentBody)
|
||||
.frame(maxWidth: .infinity, alignment: .leading)
|
||||
}
|
||||
|
||||
private func link(_ url: URL, text: String?) -> some View {
|
||||
let text = text ?? url.absoluteString
|
||||
|
||||
#if os(macOS)
|
||||
let buttonStyle = LinkButtonStyle()
|
||||
#elseif os(iOS)
|
||||
let buttonStyle = PlainButtonStyle()
|
||||
#endif
|
||||
|
||||
let button: some View = Button {
|
||||
self.changeURL?(url)
|
||||
} label: {
|
||||
Text(verbatim: text)
|
||||
.font(.documentBody)
|
||||
.foregroundColor(hovering ? .blue : Color.blue.opacity(0.8))
|
||||
.underline()
|
||||
.frame(maxWidth: .infinity, alignment: .leading)
|
||||
case let .link(url, text: linkText):
|
||||
let text = linkText ?? url.absoluteString
|
||||
Button {
|
||||
self.changeURL?(url)
|
||||
} label: {
|
||||
Text(verbatim: text)
|
||||
.font(.documentBody)
|
||||
.foregroundColor(.blue)
|
||||
.underline()
|
||||
.frame(maxWidth: .infinity, alignment: .leading)
|
||||
}.buttonStyle(LinkButtonStyle())
|
||||
case let .preformatted(text, alt: _):
|
||||
ScrollView(.horizontal) {
|
||||
Text(verbatim: text)
|
||||
.font(.documentBodyPreformatted)
|
||||
.frame(maxWidth: .infinity, alignment: .leading)
|
||||
}
|
||||
case let .heading(text, level: level):
|
||||
Text(verbatim: text)
|
||||
.font(level.font)
|
||||
.frame(maxWidth: .infinity, alignment: .leading)
|
||||
case let .unorderedListItem(text):
|
||||
// todo: should this be .firstTextBaseline?
|
||||
HStack(alignment: .top, spacing: 4) {
|
||||
Text(verbatim: "\u{2022}")
|
||||
Text(verbatim: text)
|
||||
.font(.documentBody)
|
||||
Spacer()
|
||||
}.frame(maxWidth: .infinity, alignment: .leading)
|
||||
case let .quote(text):
|
||||
HStack(spacing: 4) {
|
||||
Color.gray
|
||||
.frame(width: 4)
|
||||
Text(verbatim: text)
|
||||
.font(Font.documentBody.italic())
|
||||
.foregroundColor(.gray)
|
||||
Spacer()
|
||||
}.frame(maxWidth: .infinity, alignment: .leading)
|
||||
}
|
||||
.buttonStyle(buttonStyle)
|
||||
.onHover { hovering in
|
||||
self.hovering = hovering
|
||||
}
|
||||
|
||||
if #available(macOS 10.16, iOS 14.0, *) {
|
||||
return AnyView(button.help(url.absoluteString))
|
||||
} else {
|
||||
return AnyView(button)
|
||||
}
|
||||
}
|
||||
|
||||
private func preformatted(_ text: String) -> some View {
|
||||
ScrollView(.horizontal) {
|
||||
Text(verbatim: text)
|
||||
.font(.documentBodyPreformatted)
|
||||
.frame(maxWidth: .infinity, alignment: .leading)
|
||||
}
|
||||
}
|
||||
|
||||
private func heading(_ text: String, level: Document.HeadingLevel) -> some View {
|
||||
Text(verbatim: text)
|
||||
.font(level.font)
|
||||
.frame(maxWidth: .infinity, alignment: .leading)
|
||||
}
|
||||
|
||||
private func unorderedListItem(_ text: String) -> some View {
|
||||
// todo: should this be .firstTextBaseline?
|
||||
HStack(alignment: .top, spacing: 4) {
|
||||
Text(verbatim: "\u{2022}")
|
||||
Text(verbatim: text)
|
||||
.font(.documentBody)
|
||||
Spacer()
|
||||
}.frame(maxWidth: .infinity, alignment: .leading)
|
||||
}
|
||||
|
||||
private func quote(_ text: String) -> some View {
|
||||
HStack(spacing: 4) {
|
||||
Color.gray
|
||||
.frame(width: 4)
|
||||
Text(verbatim: text)
|
||||
.font(Font.documentBody.italic())
|
||||
.foregroundColor(.gray)
|
||||
Spacer()
|
||||
}.frame(maxWidth: .infinity, alignment: .leading)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue