Initial macOS Catalyst support
10
IceCubesActionExtension/IceCubesActionExtension.entitlements
Normal file
|
@ -0,0 +1,10 @@
|
|||
<?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>com.apple.security.app-sandbox</key>
|
||||
<true/>
|
||||
<key>com.apple.security.network.client</key>
|
||||
<true/>
|
||||
</dict>
|
||||
</plist>
|
|
@ -75,7 +75,6 @@
|
|||
9FAD85A0297456A100496AB1 /* Models in Frameworks */ = {isa = PBXBuildFile; productRef = 9FAD859F297456A100496AB1 /* Models */; };
|
||||
9FAD85A2297456A400496AB1 /* Env in Frameworks */ = {isa = PBXBuildFile; productRef = 9FAD85A1297456A400496AB1 /* Env */; };
|
||||
9FAD85A4297456A800496AB1 /* DesignSystem in Frameworks */ = {isa = PBXBuildFile; productRef = 9FAD85A3297456A800496AB1 /* DesignSystem */; };
|
||||
9FAD85A8297582F100496AB1 /* QuickLookRepresentable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9FAD85A7297582F100496AB1 /* QuickLookRepresentable.swift */; };
|
||||
9FAD85CF2975B68900496AB1 /* SideBarView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9FAD85CE2975B68900496AB1 /* SideBarView.swift */; };
|
||||
9FAE4ACB293783B000772766 /* SettingsTab.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9FAE4ACA293783B000772766 /* SettingsTab.swift */; };
|
||||
9FAE4ACE29379A5A00772766 /* KeychainSwift in Frameworks */ = {isa = PBXBuildFile; productRef = 9FAE4ACD29379A5A00772766 /* KeychainSwift */; };
|
||||
|
@ -103,7 +102,7 @@
|
|||
E9DF41FC29830FEC0003AAD2 /* UniformTypeIdentifiers.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E9DF41FB29830FEC0003AAD2 /* UniformTypeIdentifiers.framework */; };
|
||||
E9DF420129830FEC0003AAD2 /* ActionRequestHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = E9DF420029830FEC0003AAD2 /* ActionRequestHandler.swift */; };
|
||||
E9DF420329830FEC0003AAD2 /* Action.js in Resources */ = {isa = PBXBuildFile; fileRef = E9DF420229830FEC0003AAD2 /* Action.js */; };
|
||||
E9DF420729830FEC0003AAD2 /* IceCubesActionExtension.appex in Embed Foundation Extensions */ = {isa = PBXBuildFile; fileRef = E9DF41FA29830FEC0003AAD2 /* IceCubesActionExtension.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; };
|
||||
E9DF420729830FEC0003AAD2 /* IceCubesActionExtension.appex in Embed Foundation Extensions */ = {isa = PBXBuildFile; fileRef = E9DF41FA29830FEC0003AAD2 /* IceCubesActionExtension.appex */; platformFilter = ios; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; };
|
||||
FA31A9AB2A66BF7C00D5F662 /* EditTagGroupView.swift in Sources */ = {isa = PBXBuildFile; fileRef = FA31A9AA2A66BF7C00D5F662 /* EditTagGroupView.swift */; };
|
||||
FAD203D02A66D8A80030A7FD /* Symbols.swift in Sources */ = {isa = PBXBuildFile; fileRef = FAD203CF2A66D8A80030A7FD /* Symbols.swift */; };
|
||||
/* End PBXBuildFile section */
|
||||
|
@ -212,13 +211,13 @@
|
|||
9FAD858A29743F7400496AB1 /* ShareViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ShareViewController.swift; sourceTree = "<group>"; };
|
||||
9FAD858F29743F7400496AB1 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||
9FAD859629743F7E00496AB1 /* IceCubesShareExtension.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = IceCubesShareExtension.entitlements; sourceTree = "<group>"; };
|
||||
9FAD85A7297582F100496AB1 /* QuickLookRepresentable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QuickLookRepresentable.swift; sourceTree = "<group>"; };
|
||||
9FAD85CE2975B68900496AB1 /* SideBarView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SideBarView.swift; sourceTree = "<group>"; };
|
||||
9FAE4AC8293774FF00772766 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist; path = Info.plist; sourceTree = "<group>"; };
|
||||
9FAE4ACA293783B000772766 /* SettingsTab.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsTab.swift; sourceTree = "<group>"; };
|
||||
9FBFE639292A715500C250E9 /* IceCubesApp.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = IceCubesApp.app; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
9FBFE63C292A715500C250E9 /* IceCubesApp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IceCubesApp.swift; sourceTree = "<group>"; };
|
||||
9FBFE642292A715600C250E9 /* IceCubesApp.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = IceCubesApp.entitlements; sourceTree = "<group>"; };
|
||||
9FC60CB82AE6C2F600C6EAD2 /* IceCubesActionExtension.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = IceCubesActionExtension.entitlements; sourceTree = "<group>"; };
|
||||
9FCBB3D22984EFD5009B77EE /* pl */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = pl; path = pl.lproj/InfoPlist.strings; sourceTree = "<group>"; };
|
||||
9FCBB3D429859615009B77EE /* ca */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ca; path = ca.lproj/InfoPlist.strings; sourceTree = "<group>"; };
|
||||
9FD34822293D06E800DB0EE9 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
|
||||
|
@ -343,7 +342,6 @@
|
|||
9FBFE63C292A715500C250E9 /* IceCubesApp.swift */,
|
||||
9F398AA52935FE8A00A889F2 /* AppRegistry.swift */,
|
||||
639CDF9B296AC82F00C35E58 /* SafariRouter.swift */,
|
||||
9FAD85A7297582F100496AB1 /* QuickLookRepresentable.swift */,
|
||||
9FAD85CE2975B68900496AB1 /* SideBarView.swift */,
|
||||
);
|
||||
path = App;
|
||||
|
@ -517,6 +515,7 @@
|
|||
E9DF41FD29830FEC0003AAD2 /* IceCubesActionExtension */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
9FC60CB82AE6C2F600C6EAD2 /* IceCubesActionExtension.entitlements */,
|
||||
E9DF420029830FEC0003AAD2 /* ActionRequestHandler.swift */,
|
||||
E9DF420229830FEC0003AAD2 /* Action.js */,
|
||||
E9DF420429830FEC0003AAD2 /* Info.plist */,
|
||||
|
@ -818,7 +817,6 @@
|
|||
9F55C68D2955968700F94077 /* ExploreTab.swift in Sources */,
|
||||
9F1E8B47298EBCBB00609F80 /* HapticSettingsView.swift in Sources */,
|
||||
9F2A5411296A1429009B2D7C /* PushNotificationsView.swift in Sources */,
|
||||
9FAD85A8297582F100496AB1 /* QuickLookRepresentable.swift in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
|
@ -847,6 +845,7 @@
|
|||
};
|
||||
E9DF420629830FEC0003AAD2 /* PBXTargetDependency */ = {
|
||||
isa = PBXTargetDependency;
|
||||
platformFilter = ios;
|
||||
target = E9DF41F929830FEC0003AAD2 /* IceCubesActionExtension */;
|
||||
targetProxy = E9DF420529830FEC0003AAD2 /* PBXContainerItemProxy */;
|
||||
};
|
||||
|
@ -881,6 +880,7 @@
|
|||
CODE_SIGN_ENTITLEMENTS = IceCubesNotifications/IceCubesNotifications.entitlements;
|
||||
CODE_SIGN_IDENTITY = "-";
|
||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "Apple Development";
|
||||
"CODE_SIGN_IDENTITY[sdk=macosx*]" = "Apple Development";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 730;
|
||||
DEVELOPMENT_TEAM = "$(DEVELOPMENT_TEAM)";
|
||||
|
@ -899,6 +899,9 @@
|
|||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SDKROOT = iphoneos;
|
||||
SKIP_INSTALL = YES;
|
||||
SUPPORTED_PLATFORMS = "iphoneos iphonesimulator";
|
||||
SUPPORTS_MACCATALYST = YES;
|
||||
SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = NO;
|
||||
SWIFT_EMIT_LOC_STRINGS = YES;
|
||||
SWIFT_VERSION = 5.0;
|
||||
TARGETED_DEVICE_FAMILY = "1,2";
|
||||
|
@ -911,6 +914,7 @@
|
|||
CODE_SIGN_ENTITLEMENTS = IceCubesNotifications/IceCubesNotifications.entitlements;
|
||||
CODE_SIGN_IDENTITY = "-";
|
||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "Apple Development";
|
||||
"CODE_SIGN_IDENTITY[sdk=macosx*]" = "Apple Development";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 730;
|
||||
DEVELOPMENT_TEAM = "$(DEVELOPMENT_TEAM)";
|
||||
|
@ -929,6 +933,9 @@
|
|||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SDKROOT = iphoneos;
|
||||
SKIP_INSTALL = YES;
|
||||
SUPPORTED_PLATFORMS = "iphoneos iphonesimulator";
|
||||
SUPPORTS_MACCATALYST = YES;
|
||||
SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = NO;
|
||||
SWIFT_EMIT_LOC_STRINGS = YES;
|
||||
SWIFT_VERSION = 5.0;
|
||||
TARGETED_DEVICE_FAMILY = "1,2";
|
||||
|
@ -942,6 +949,7 @@
|
|||
CODE_SIGN_ENTITLEMENTS = IceCubesShareExtension/IceCubesShareExtension.entitlements;
|
||||
CODE_SIGN_IDENTITY = "-";
|
||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "Apple Development";
|
||||
"CODE_SIGN_IDENTITY[sdk=macosx*]" = "Apple Development";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 730;
|
||||
DEVELOPMENT_TEAM = "$(DEVELOPMENT_TEAM)";
|
||||
|
@ -960,6 +968,9 @@
|
|||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SDKROOT = iphoneos;
|
||||
SKIP_INSTALL = YES;
|
||||
SUPPORTED_PLATFORMS = "iphoneos iphonesimulator";
|
||||
SUPPORTS_MACCATALYST = YES;
|
||||
SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = NO;
|
||||
SWIFT_EMIT_LOC_STRINGS = YES;
|
||||
SWIFT_VERSION = 5.0;
|
||||
TARGETED_DEVICE_FAMILY = "1,2";
|
||||
|
@ -972,6 +983,7 @@
|
|||
CODE_SIGN_ENTITLEMENTS = IceCubesShareExtension/IceCubesShareExtension.entitlements;
|
||||
CODE_SIGN_IDENTITY = "-";
|
||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "Apple Development";
|
||||
"CODE_SIGN_IDENTITY[sdk=macosx*]" = "Apple Development";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 730;
|
||||
DEVELOPMENT_TEAM = "$(DEVELOPMENT_TEAM)";
|
||||
|
@ -990,6 +1002,9 @@
|
|||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SDKROOT = iphoneos;
|
||||
SKIP_INSTALL = YES;
|
||||
SUPPORTED_PLATFORMS = "iphoneos iphonesimulator";
|
||||
SUPPORTS_MACCATALYST = YES;
|
||||
SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = NO;
|
||||
SWIFT_EMIT_LOC_STRINGS = YES;
|
||||
SWIFT_VERSION = 5.0;
|
||||
TARGETED_DEVICE_FAMILY = "1,2";
|
||||
|
@ -1147,6 +1162,7 @@
|
|||
INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.social-networking";
|
||||
INFOPLIST_KEY_NSCameraUsageDescription = "Upload photos & videos to Mastodon";
|
||||
INFOPLIST_KEY_NSPhotoLibraryUsageDescription = "Upload photos & videos to Mastodon";
|
||||
INFOPLIST_KEY_UIApplicationSceneManifest_Generation = YES;
|
||||
"INFOPLIST_KEY_UIApplicationSceneManifest_Generation[sdk=iphoneos*]" = YES;
|
||||
"INFOPLIST_KEY_UIApplicationSceneManifest_Generation[sdk=iphonesimulator*]" = YES;
|
||||
"INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents[sdk=iphoneos*]" = YES;
|
||||
|
@ -1166,8 +1182,8 @@
|
|||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SDKROOT = auto;
|
||||
SUPPORTED_PLATFORMS = "iphoneos iphonesimulator";
|
||||
SUPPORTS_MACCATALYST = NO;
|
||||
SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = YES;
|
||||
SUPPORTS_MACCATALYST = YES;
|
||||
SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = NO;
|
||||
SWIFT_EMIT_LOC_STRINGS = YES;
|
||||
SWIFT_STRICT_CONCURRENCY = complete;
|
||||
SWIFT_VERSION = 5.0;
|
||||
|
@ -1200,6 +1216,7 @@
|
|||
INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.social-networking";
|
||||
INFOPLIST_KEY_NSCameraUsageDescription = "Upload photos & videos to Mastodon";
|
||||
INFOPLIST_KEY_NSPhotoLibraryUsageDescription = "Upload photos & videos to Mastodon";
|
||||
INFOPLIST_KEY_UIApplicationSceneManifest_Generation = YES;
|
||||
"INFOPLIST_KEY_UIApplicationSceneManifest_Generation[sdk=iphoneos*]" = YES;
|
||||
"INFOPLIST_KEY_UIApplicationSceneManifest_Generation[sdk=iphonesimulator*]" = YES;
|
||||
"INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents[sdk=iphoneos*]" = YES;
|
||||
|
@ -1219,8 +1236,8 @@
|
|||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SDKROOT = auto;
|
||||
SUPPORTED_PLATFORMS = "iphoneos iphonesimulator";
|
||||
SUPPORTS_MACCATALYST = NO;
|
||||
SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = YES;
|
||||
SUPPORTS_MACCATALYST = YES;
|
||||
SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = NO;
|
||||
SWIFT_EMIT_LOC_STRINGS = YES;
|
||||
SWIFT_STRICT_CONCURRENCY = complete;
|
||||
SWIFT_VERSION = 5.0;
|
||||
|
@ -1232,6 +1249,7 @@
|
|||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = ActionIcon;
|
||||
CODE_SIGN_ENTITLEMENTS = IceCubesActionExtension/IceCubesActionExtension.entitlements;
|
||||
CODE_SIGN_IDENTITY = "-";
|
||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "Apple Development";
|
||||
"CODE_SIGN_IDENTITY[sdk=macosx*]" = "Apple Development";
|
||||
|
@ -1253,6 +1271,9 @@
|
|||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SDKROOT = iphoneos;
|
||||
SKIP_INSTALL = YES;
|
||||
SUPPORTED_PLATFORMS = "iphoneos iphonesimulator";
|
||||
SUPPORTS_MACCATALYST = YES;
|
||||
SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = NO;
|
||||
SWIFT_EMIT_LOC_STRINGS = YES;
|
||||
SWIFT_VERSION = 5.0;
|
||||
TARGETED_DEVICE_FAMILY = "1,2";
|
||||
|
@ -1263,6 +1284,7 @@
|
|||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = ActionIcon;
|
||||
CODE_SIGN_ENTITLEMENTS = IceCubesActionExtension/IceCubesActionExtension.entitlements;
|
||||
CODE_SIGN_IDENTITY = "-";
|
||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "Apple Development";
|
||||
"CODE_SIGN_IDENTITY[sdk=macosx*]" = "Apple Development";
|
||||
|
@ -1284,6 +1306,9 @@
|
|||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SDKROOT = iphoneos;
|
||||
SKIP_INSTALL = YES;
|
||||
SUPPORTED_PLATFORMS = "iphoneos iphonesimulator";
|
||||
SUPPORTS_MACCATALYST = YES;
|
||||
SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = NO;
|
||||
SWIFT_EMIT_LOC_STRINGS = YES;
|
||||
SWIFT_VERSION = 5.0;
|
||||
TARGETED_DEVICE_FAMILY = "1,2";
|
||||
|
|
|
@ -180,3 +180,9 @@ struct ActivityView: UIViewControllerRepresentable {
|
|||
|
||||
func updateUIViewController(_: UIActivityViewController, context _: UIViewControllerRepresentableContext<ActivityView>) {}
|
||||
}
|
||||
|
||||
extension URL: Identifiable {
|
||||
public var id: String {
|
||||
absoluteString
|
||||
}
|
||||
}
|
||||
|
|
|
@ -37,6 +37,11 @@ struct IceCubesApp: App {
|
|||
}
|
||||
|
||||
var body: some Scene {
|
||||
appScene
|
||||
otherScenes
|
||||
}
|
||||
|
||||
private var appScene: some Scene {
|
||||
WindowGroup {
|
||||
appView
|
||||
.applyTheme(theme)
|
||||
|
@ -60,14 +65,8 @@ struct IceCubesApp: App {
|
|||
attachments: quickLook.mediaAttachments)
|
||||
.presentationBackground(.ultraThinMaterial)
|
||||
.presentationCornerRadius(16)
|
||||
.environment(userPreferences)
|
||||
.environment(theme)
|
||||
.withEnvironments()
|
||||
}
|
||||
.fullScreenCover(item: $quickLook.url, content: { url in
|
||||
QuickLookPreview(selectedURL: url, urls: quickLook.urls)
|
||||
.edgesIgnoringSafeArea(.bottom)
|
||||
.background(TransparentBackground())
|
||||
})
|
||||
.onChange(of: pushNotificationsService.handledNotification) { _, newValue in
|
||||
if newValue != nil {
|
||||
pushNotificationsService.handledNotification = nil
|
||||
|
@ -99,6 +98,7 @@ struct IceCubesApp: App {
|
|||
watcher.watch(streams: [.user, .direct])
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ViewBuilder
|
||||
|
@ -208,6 +208,27 @@ struct IceCubesApp: App {
|
|||
.id(appAccountsManager.currentClient.id)
|
||||
}
|
||||
|
||||
private var otherScenes: some Scene {
|
||||
WindowGroup(for: WindowDestination.self) { destination in
|
||||
Group {
|
||||
switch destination.wrappedValue {
|
||||
case let .newStatusEditor(visibility):
|
||||
StatusEditorView(mode: .new(visibility: visibility))
|
||||
case let .mediaViewer(attachments, selectedAttachment):
|
||||
MediaUIView(selectedAttachment: selectedAttachment,
|
||||
attachments: attachments)
|
||||
case .none:
|
||||
EmptyView()
|
||||
}
|
||||
}
|
||||
.withEnvironments()
|
||||
.withModelContainer()
|
||||
.applyTheme(theme)
|
||||
}
|
||||
.defaultSize(width: 600, height: 800)
|
||||
.windowResizability(.automatic)
|
||||
}
|
||||
|
||||
private func setNewClientsInEnv(client: Client) {
|
||||
currentAccount.setClient(client: client)
|
||||
currentInstance.setClient(client: client)
|
||||
|
|
|
@ -1,101 +0,0 @@
|
|||
import QuickLook
|
||||
import SwiftUI
|
||||
import UIKit
|
||||
|
||||
extension URL: Identifiable {
|
||||
public var id: String {
|
||||
absoluteString
|
||||
}
|
||||
}
|
||||
|
||||
struct QuickLookPreview: UIViewControllerRepresentable {
|
||||
let selectedURL: URL
|
||||
let urls: [URL]
|
||||
|
||||
func makeUIViewController(context _: Context) -> UIViewController {
|
||||
AppQLPreviewController(selectedURL: selectedURL, urls: urls)
|
||||
}
|
||||
|
||||
func updateUIViewController(
|
||||
_: UIViewController, context _: Context
|
||||
) {}
|
||||
}
|
||||
|
||||
@MainActor
|
||||
class AppQLPreviewController: UIViewController {
|
||||
let selectedURL: URL
|
||||
let urls: [URL]
|
||||
|
||||
var qlController: QLPreviewController?
|
||||
|
||||
init(selectedURL: URL, urls: [URL]) {
|
||||
self.selectedURL = selectedURL
|
||||
self.urls = urls
|
||||
super.init(nibName: nil, bundle: nil)
|
||||
}
|
||||
|
||||
@available(*, unavailable)
|
||||
required init?(coder _: NSCoder) {
|
||||
fatalError("init(coder:) has not been implemented")
|
||||
}
|
||||
|
||||
override func viewWillAppear(_ animated: Bool) {
|
||||
super.viewWillAppear(animated)
|
||||
if qlController == nil {
|
||||
qlController = QLPreviewController()
|
||||
qlController?.dataSource = self
|
||||
qlController?.delegate = self
|
||||
qlController?.currentPreviewItemIndex = urls.firstIndex(of: selectedURL) ?? 0
|
||||
present(qlController!, animated: true)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extension AppQLPreviewController: QLPreviewControllerDataSource {
|
||||
nonisolated func numberOfPreviewItems(in _: QLPreviewController) -> Int {
|
||||
urls.count
|
||||
}
|
||||
|
||||
nonisolated func previewController(_: QLPreviewController, previewItemAt index: Int) -> QLPreviewItem {
|
||||
urls[index] as QLPreviewItem
|
||||
}
|
||||
}
|
||||
|
||||
extension AppQLPreviewController: QLPreviewControllerDelegate {
|
||||
nonisolated func previewController(_: QLPreviewController, editingModeFor _: QLPreviewItem) -> QLPreviewItemEditingMode {
|
||||
.createCopy
|
||||
}
|
||||
|
||||
nonisolated func previewControllerWillDismiss(_: QLPreviewController) {
|
||||
Task { @MainActor in
|
||||
dismiss(animated: true)
|
||||
}
|
||||
}
|
||||
|
||||
nonisolated func previewControllerDidDismiss(_: QLPreviewController) {
|
||||
Task { @MainActor in
|
||||
dismiss(animated: true)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct TransparentBackground: UIViewControllerRepresentable {
|
||||
public func makeUIViewController(context _: Context) -> UIViewController {
|
||||
TransparentController()
|
||||
}
|
||||
|
||||
public func updateUIViewController(_: UIViewController, context _: Context) {}
|
||||
|
||||
class TransparentController: UIViewController {
|
||||
override func viewDidLoad() {
|
||||
super.viewDidLoad()
|
||||
view.backgroundColor = .clear
|
||||
}
|
||||
|
||||
override func willMove(toParent parent: UIViewController?) {
|
||||
super.willMove(toParent: parent)
|
||||
parent?.view?.backgroundColor = .clear
|
||||
parent?.modalPresentationStyle = .overCurrentContext
|
||||
}
|
||||
}
|
||||
}
|
|
@ -42,7 +42,7 @@ private struct SafariRouter: ViewModifier {
|
|||
return .handled
|
||||
}
|
||||
}
|
||||
guard preferences.preferredBrowser == .inAppSafari, !ProcessInfo.processInfo.isiOSAppOnMac else { return .systemAction }
|
||||
guard preferences.preferredBrowser == .inAppSafari, !ProcessInfo.processInfo.isMacCatalystApp else { return .systemAction }
|
||||
// SFSafariViewController only supports initial URLs with http:// or https:// schemes.
|
||||
guard let scheme = url.scheme, ["https", "http"].contains(scheme.lowercased()) else {
|
||||
return .systemAction
|
||||
|
|
|
@ -7,6 +7,8 @@ import SwiftUI
|
|||
|
||||
@MainActor
|
||||
struct SideBarView<Content: View>: View {
|
||||
@Environment(\.openWindow) private var openWindow
|
||||
|
||||
@Environment(AppAccountsManager.self) private var appAccounts
|
||||
@Environment(CurrentAccount.self) private var currentAccount
|
||||
@Environment(Theme.self) private var theme
|
||||
|
@ -55,7 +57,11 @@ struct SideBarView<Content: View>: View {
|
|||
|
||||
private var postButton: some View {
|
||||
Button {
|
||||
routerPath.presentedSheet = .newStatusEditor(visibility: userPreferences.postVisibility)
|
||||
if ProcessInfo.processInfo.isMacCatalystApp {
|
||||
openWindow(value: WindowDestination.newStatusEditor(visibility: userPreferences.postVisibility))
|
||||
} else {
|
||||
routerPath.presentedSheet = .newStatusEditor(visibility: userPreferences.postVisibility)
|
||||
}
|
||||
} label: {
|
||||
Image(systemName: "square.and.pencil")
|
||||
.resizable()
|
||||
|
|
|
@ -169,7 +169,7 @@ struct SettingsTabs: View {
|
|||
private var otherSections: some View {
|
||||
@Bindable var preferences = preferences
|
||||
Section("settings.section.other") {
|
||||
if !ProcessInfo.processInfo.isiOSAppOnMac {
|
||||
if !ProcessInfo.processInfo.isMacCatalystApp{
|
||||
Picker(selection: $preferences.preferredBrowser) {
|
||||
ForEach(PreferredBrowser.allCases, id: \.rawValue) { browser in
|
||||
switch browser {
|
||||
|
@ -202,7 +202,7 @@ struct SettingsTabs: View {
|
|||
|
||||
private var appSection: some View {
|
||||
Section {
|
||||
if !ProcessInfo.processInfo.isiOSAppOnMac {
|
||||
if !ProcessInfo.processInfo.isMacCatalystApp {
|
||||
NavigationLink(destination: IconSelectorView()) {
|
||||
Label {
|
||||
Text("settings.app.icon")
|
||||
|
|
Before Width: | Height: | Size: 24 KiB |
Before Width: | Height: | Size: 819 B |
Before Width: | Height: | Size: 84 KiB |
Before Width: | Height: | Size: 2.3 KiB |
Before Width: | Height: | Size: 308 KiB |
0
IceCubesApp/Assets.xcassets/AppIcon.appiconset/60.png
Executable file → Normal file
Before Width: | Height: | Size: 6.3 KiB After Width: | Height: | Size: 6.3 KiB |
Before Width: | Height: | Size: 7.1 KiB |
|
@ -1,284 +1,218 @@
|
|||
{
|
||||
"images": [
|
||||
{
|
||||
"size": "60x60",
|
||||
"expected-size": "180",
|
||||
"filename": "180.png",
|
||||
"folder": "Assets.xcassets/AppIcon.appiconset/",
|
||||
"idiom": "iphone",
|
||||
"scale": "3x"
|
||||
},
|
||||
{
|
||||
"size": "40x40",
|
||||
"expected-size": "80",
|
||||
"filename": "80.png",
|
||||
"folder": "Assets.xcassets/AppIcon.appiconset/",
|
||||
"idiom": "iphone",
|
||||
"scale": "2x"
|
||||
},
|
||||
{
|
||||
"size": "40x40",
|
||||
"expected-size": "120",
|
||||
"filename": "120.png",
|
||||
"folder": "Assets.xcassets/AppIcon.appiconset/",
|
||||
"idiom": "iphone",
|
||||
"scale": "3x"
|
||||
},
|
||||
{
|
||||
"size": "60x60",
|
||||
"expected-size": "120",
|
||||
"filename": "120.png",
|
||||
"folder": "Assets.xcassets/AppIcon.appiconset/",
|
||||
"idiom": "iphone",
|
||||
"scale": "2x"
|
||||
},
|
||||
{
|
||||
"size": "57x57",
|
||||
"expected-size": "57",
|
||||
"filename": "57.png",
|
||||
"folder": "Assets.xcassets/AppIcon.appiconset/",
|
||||
"idiom": "iphone",
|
||||
"scale": "1x"
|
||||
},
|
||||
{
|
||||
"size": "29x29",
|
||||
"expected-size": "58",
|
||||
"filename": "58.png",
|
||||
"folder": "Assets.xcassets/AppIcon.appiconset/",
|
||||
"idiom": "iphone",
|
||||
"scale": "2x"
|
||||
},
|
||||
{
|
||||
"size": "29x29",
|
||||
"expected-size": "29",
|
||||
"filename": "29.png",
|
||||
"folder": "Assets.xcassets/AppIcon.appiconset/",
|
||||
"idiom": "iphone",
|
||||
"scale": "1x"
|
||||
},
|
||||
{
|
||||
"size": "29x29",
|
||||
"expected-size": "87",
|
||||
"filename": "87.png",
|
||||
"folder": "Assets.xcassets/AppIcon.appiconset/",
|
||||
"idiom": "iphone",
|
||||
"scale": "3x"
|
||||
},
|
||||
{
|
||||
"size": "57x57",
|
||||
"expected-size": "114",
|
||||
"filename": "114.png",
|
||||
"folder": "Assets.xcassets/AppIcon.appiconset/",
|
||||
"idiom": "iphone",
|
||||
"scale": "2x"
|
||||
},
|
||||
{
|
||||
"size": "20x20",
|
||||
"expected-size": "40",
|
||||
"filename": "40.png",
|
||||
"folder": "Assets.xcassets/AppIcon.appiconset/",
|
||||
"idiom": "iphone",
|
||||
"scale": "2x"
|
||||
},
|
||||
{
|
||||
"size": "20x20",
|
||||
"expected-size": "60",
|
||||
"filename": "60.png",
|
||||
"folder": "Assets.xcassets/AppIcon.appiconset/",
|
||||
"idiom": "iphone",
|
||||
"scale": "3x"
|
||||
},
|
||||
{
|
||||
"size": "1024x1024",
|
||||
"filename": "1024.png",
|
||||
"expected-size": "1024",
|
||||
"idiom": "ios-marketing",
|
||||
"folder": "Assets.xcassets/AppIcon.appiconset/",
|
||||
"scale": "1x"
|
||||
},
|
||||
{
|
||||
"size": "40x40",
|
||||
"expected-size": "80",
|
||||
"filename": "80.png",
|
||||
"folder": "Assets.xcassets/AppIcon.appiconset/",
|
||||
"idiom": "ipad",
|
||||
"scale": "2x"
|
||||
},
|
||||
{
|
||||
"size": "72x72",
|
||||
"expected-size": "72",
|
||||
"filename": "72.png",
|
||||
"folder": "Assets.xcassets/AppIcon.appiconset/",
|
||||
"idiom": "ipad",
|
||||
"scale": "1x"
|
||||
},
|
||||
{
|
||||
"size": "76x76",
|
||||
"expected-size": "152",
|
||||
"filename": "152.png",
|
||||
"folder": "Assets.xcassets/AppIcon.appiconset/",
|
||||
"idiom": "ipad",
|
||||
"scale": "2x"
|
||||
},
|
||||
{
|
||||
"size": "50x50",
|
||||
"expected-size": "100",
|
||||
"filename": "100.png",
|
||||
"folder": "Assets.xcassets/AppIcon.appiconset/",
|
||||
"idiom": "ipad",
|
||||
"scale": "2x"
|
||||
},
|
||||
{
|
||||
"size": "29x29",
|
||||
"expected-size": "58",
|
||||
"filename": "58.png",
|
||||
"folder": "Assets.xcassets/AppIcon.appiconset/",
|
||||
"idiom": "ipad",
|
||||
"scale": "2x"
|
||||
},
|
||||
{
|
||||
"size": "76x76",
|
||||
"expected-size": "76",
|
||||
"filename": "76.png",
|
||||
"folder": "Assets.xcassets/AppIcon.appiconset/",
|
||||
"idiom": "ipad",
|
||||
"scale": "1x"
|
||||
},
|
||||
{
|
||||
"size": "29x29",
|
||||
"expected-size": "29",
|
||||
"filename": "29.png",
|
||||
"folder": "Assets.xcassets/AppIcon.appiconset/",
|
||||
"idiom": "ipad",
|
||||
"scale": "1x"
|
||||
},
|
||||
{
|
||||
"size": "50x50",
|
||||
"expected-size": "50",
|
||||
"filename": "50.png",
|
||||
"folder": "Assets.xcassets/AppIcon.appiconset/",
|
||||
"idiom": "ipad",
|
||||
"scale": "1x"
|
||||
},
|
||||
{
|
||||
"size": "72x72",
|
||||
"expected-size": "144",
|
||||
"filename": "144.png",
|
||||
"folder": "Assets.xcassets/AppIcon.appiconset/",
|
||||
"idiom": "ipad",
|
||||
"scale": "2x"
|
||||
},
|
||||
{
|
||||
"size": "40x40",
|
||||
"expected-size": "40",
|
||||
"filename": "40.png",
|
||||
"folder": "Assets.xcassets/AppIcon.appiconset/",
|
||||
"idiom": "ipad",
|
||||
"scale": "1x"
|
||||
},
|
||||
{
|
||||
"size": "83.5x83.5",
|
||||
"expected-size": "167",
|
||||
"filename": "167.png",
|
||||
"folder": "Assets.xcassets/AppIcon.appiconset/",
|
||||
"idiom": "ipad",
|
||||
"scale": "2x"
|
||||
},
|
||||
{
|
||||
"size": "20x20",
|
||||
"expected-size": "20",
|
||||
"filename": "20.png",
|
||||
"folder": "Assets.xcassets/AppIcon.appiconset/",
|
||||
"idiom": "ipad",
|
||||
"scale": "1x"
|
||||
},
|
||||
{
|
||||
"size": "20x20",
|
||||
"expected-size": "40",
|
||||
"filename": "40.png",
|
||||
"folder": "Assets.xcassets/AppIcon.appiconset/",
|
||||
"idiom": "ipad",
|
||||
"scale": "2x"
|
||||
},
|
||||
{
|
||||
"size": "128x128",
|
||||
"expected-size": "128",
|
||||
"filename": "128.png",
|
||||
"folder": "Assets.xcassets/AppIcon.appiconset/",
|
||||
"idiom": "mac",
|
||||
"scale": "1x"
|
||||
},
|
||||
{
|
||||
"size": "256x256",
|
||||
"expected-size": "256",
|
||||
"filename": "256.png",
|
||||
"folder": "Assets.xcassets/AppIcon.appiconset/",
|
||||
"idiom": "mac",
|
||||
"scale": "1x"
|
||||
},
|
||||
{
|
||||
"size": "128x128",
|
||||
"expected-size": "256",
|
||||
"filename": "256.png",
|
||||
"folder": "Assets.xcassets/AppIcon.appiconset/",
|
||||
"idiom": "mac",
|
||||
"scale": "2x"
|
||||
},
|
||||
{
|
||||
"size": "256x256",
|
||||
"expected-size": "512",
|
||||
"filename": "512.png",
|
||||
"folder": "Assets.xcassets/AppIcon.appiconset/",
|
||||
"idiom": "mac",
|
||||
"scale": "2x"
|
||||
},
|
||||
{
|
||||
"size": "32x32",
|
||||
"expected-size": "32",
|
||||
"filename": "32.png",
|
||||
"folder": "Assets.xcassets/AppIcon.appiconset/",
|
||||
"idiom": "mac",
|
||||
"scale": "1x"
|
||||
},
|
||||
{
|
||||
"size": "512x512",
|
||||
"expected-size": "512",
|
||||
"filename": "512.png",
|
||||
"folder": "Assets.xcassets/AppIcon.appiconset/",
|
||||
"idiom": "mac",
|
||||
"scale": "1x"
|
||||
},
|
||||
{
|
||||
"size": "16x16",
|
||||
"expected-size": "16",
|
||||
"filename": "16.png",
|
||||
"folder": "Assets.xcassets/AppIcon.appiconset/",
|
||||
"idiom": "mac",
|
||||
"scale": "1x"
|
||||
},
|
||||
{
|
||||
"size": "16x16",
|
||||
"expected-size": "32",
|
||||
"filename": "32.png",
|
||||
"folder": "Assets.xcassets/AppIcon.appiconset/",
|
||||
"idiom": "mac",
|
||||
"scale": "2x"
|
||||
},
|
||||
{
|
||||
"size": "32x32",
|
||||
"expected-size": "64",
|
||||
"filename": "64.png",
|
||||
"folder": "Assets.xcassets/AppIcon.appiconset/",
|
||||
"idiom": "mac",
|
||||
"scale": "2x"
|
||||
},
|
||||
{
|
||||
"size": "512x512",
|
||||
"expected-size": "1024",
|
||||
"filename": "1024.png",
|
||||
"folder": "Assets.xcassets/AppIcon.appiconset/",
|
||||
"idiom": "mac",
|
||||
"scale": "2x"
|
||||
}
|
||||
]
|
||||
"images" : [
|
||||
{
|
||||
"filename" : "40.png",
|
||||
"idiom" : "iphone",
|
||||
"scale" : "2x",
|
||||
"size" : "20x20"
|
||||
},
|
||||
{
|
||||
"filename" : "60.png",
|
||||
"idiom" : "iphone",
|
||||
"scale" : "3x",
|
||||
"size" : "20x20"
|
||||
},
|
||||
{
|
||||
"filename" : "29.png",
|
||||
"idiom" : "iphone",
|
||||
"scale" : "1x",
|
||||
"size" : "29x29"
|
||||
},
|
||||
{
|
||||
"filename" : "58.png",
|
||||
"idiom" : "iphone",
|
||||
"scale" : "2x",
|
||||
"size" : "29x29"
|
||||
},
|
||||
{
|
||||
"filename" : "87.png",
|
||||
"idiom" : "iphone",
|
||||
"scale" : "3x",
|
||||
"size" : "29x29"
|
||||
},
|
||||
{
|
||||
"filename" : "80.png",
|
||||
"idiom" : "iphone",
|
||||
"scale" : "2x",
|
||||
"size" : "40x40"
|
||||
},
|
||||
{
|
||||
"filename" : "120.png",
|
||||
"idiom" : "iphone",
|
||||
"scale" : "3x",
|
||||
"size" : "40x40"
|
||||
},
|
||||
{
|
||||
"filename" : "57.png",
|
||||
"idiom" : "iphone",
|
||||
"scale" : "1x",
|
||||
"size" : "57x57"
|
||||
},
|
||||
{
|
||||
"filename" : "114.png",
|
||||
"idiom" : "iphone",
|
||||
"scale" : "2x",
|
||||
"size" : "57x57"
|
||||
},
|
||||
{
|
||||
"filename" : "120.png",
|
||||
"idiom" : "iphone",
|
||||
"scale" : "2x",
|
||||
"size" : "60x60"
|
||||
},
|
||||
{
|
||||
"filename" : "180.png",
|
||||
"idiom" : "iphone",
|
||||
"scale" : "3x",
|
||||
"size" : "60x60"
|
||||
},
|
||||
{
|
||||
"filename" : "20.png",
|
||||
"idiom" : "ipad",
|
||||
"scale" : "1x",
|
||||
"size" : "20x20"
|
||||
},
|
||||
{
|
||||
"filename" : "40.png",
|
||||
"idiom" : "ipad",
|
||||
"scale" : "2x",
|
||||
"size" : "20x20"
|
||||
},
|
||||
{
|
||||
"filename" : "29.png",
|
||||
"idiom" : "ipad",
|
||||
"scale" : "1x",
|
||||
"size" : "29x29"
|
||||
},
|
||||
{
|
||||
"filename" : "58.png",
|
||||
"idiom" : "ipad",
|
||||
"scale" : "2x",
|
||||
"size" : "29x29"
|
||||
},
|
||||
{
|
||||
"filename" : "40.png",
|
||||
"idiom" : "ipad",
|
||||
"scale" : "1x",
|
||||
"size" : "40x40"
|
||||
},
|
||||
{
|
||||
"filename" : "80.png",
|
||||
"idiom" : "ipad",
|
||||
"scale" : "2x",
|
||||
"size" : "40x40"
|
||||
},
|
||||
{
|
||||
"filename" : "50.png",
|
||||
"idiom" : "ipad",
|
||||
"scale" : "1x",
|
||||
"size" : "50x50"
|
||||
},
|
||||
{
|
||||
"filename" : "100.png",
|
||||
"idiom" : "ipad",
|
||||
"scale" : "2x",
|
||||
"size" : "50x50"
|
||||
},
|
||||
{
|
||||
"filename" : "72.png",
|
||||
"idiom" : "ipad",
|
||||
"scale" : "1x",
|
||||
"size" : "72x72"
|
||||
},
|
||||
{
|
||||
"filename" : "144.png",
|
||||
"idiom" : "ipad",
|
||||
"scale" : "2x",
|
||||
"size" : "72x72"
|
||||
},
|
||||
{
|
||||
"filename" : "76.png",
|
||||
"idiom" : "ipad",
|
||||
"scale" : "1x",
|
||||
"size" : "76x76"
|
||||
},
|
||||
{
|
||||
"filename" : "152.png",
|
||||
"idiom" : "ipad",
|
||||
"scale" : "2x",
|
||||
"size" : "76x76"
|
||||
},
|
||||
{
|
||||
"filename" : "167.png",
|
||||
"idiom" : "ipad",
|
||||
"scale" : "2x",
|
||||
"size" : "83.5x83.5"
|
||||
},
|
||||
{
|
||||
"filename" : "1024.png",
|
||||
"idiom" : "ios-marketing",
|
||||
"scale" : "1x",
|
||||
"size" : "1024x1024"
|
||||
},
|
||||
{
|
||||
"filename" : "Icon-16.png",
|
||||
"idiom" : "mac",
|
||||
"scale" : "1x",
|
||||
"size" : "16x16"
|
||||
},
|
||||
{
|
||||
"filename" : "Icon-32.png",
|
||||
"idiom" : "mac",
|
||||
"scale" : "2x",
|
||||
"size" : "16x16"
|
||||
},
|
||||
{
|
||||
"filename" : "Icon-32 1.png",
|
||||
"idiom" : "mac",
|
||||
"scale" : "1x",
|
||||
"size" : "32x32"
|
||||
},
|
||||
{
|
||||
"filename" : "Icon-64.png",
|
||||
"idiom" : "mac",
|
||||
"scale" : "2x",
|
||||
"size" : "32x32"
|
||||
},
|
||||
{
|
||||
"filename" : "Icon-128.png",
|
||||
"idiom" : "mac",
|
||||
"scale" : "1x",
|
||||
"size" : "128x128"
|
||||
},
|
||||
{
|
||||
"filename" : "Icon-256 1.png",
|
||||
"idiom" : "mac",
|
||||
"scale" : "2x",
|
||||
"size" : "128x128"
|
||||
},
|
||||
{
|
||||
"filename" : "Icon-256.png",
|
||||
"idiom" : "mac",
|
||||
"scale" : "1x",
|
||||
"size" : "256x256"
|
||||
},
|
||||
{
|
||||
"filename" : "Icon-512 1.png",
|
||||
"idiom" : "mac",
|
||||
"scale" : "2x",
|
||||
"size" : "256x256"
|
||||
},
|
||||
{
|
||||
"filename" : "Icon-512.png",
|
||||
"idiom" : "mac",
|
||||
"scale" : "1x",
|
||||
"size" : "512x512"
|
||||
},
|
||||
{
|
||||
"filename" : "Icon-1024.png",
|
||||
"idiom" : "mac",
|
||||
"scale" : "2x",
|
||||
"size" : "512x512"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
BIN
IceCubesApp/Assets.xcassets/AppIcon.appiconset/Icon-1024.png
Normal file
After Width: | Height: | Size: 749 KiB |
BIN
IceCubesApp/Assets.xcassets/AppIcon.appiconset/Icon-128.png
Normal file
After Width: | Height: | Size: 17 KiB |
BIN
IceCubesApp/Assets.xcassets/AppIcon.appiconset/Icon-16.png
Normal file
After Width: | Height: | Size: 653 B |
BIN
IceCubesApp/Assets.xcassets/AppIcon.appiconset/Icon-256 1.png
Normal file
After Width: | Height: | Size: 56 KiB |
BIN
IceCubesApp/Assets.xcassets/AppIcon.appiconset/Icon-256.png
Normal file
After Width: | Height: | Size: 56 KiB |
BIN
IceCubesApp/Assets.xcassets/AppIcon.appiconset/Icon-32 1.png
Normal file
After Width: | Height: | Size: 1.7 KiB |
BIN
IceCubesApp/Assets.xcassets/AppIcon.appiconset/Icon-32.png
Normal file
After Width: | Height: | Size: 1.7 KiB |
BIN
IceCubesApp/Assets.xcassets/AppIcon.appiconset/Icon-512 1.png
Normal file
After Width: | Height: | Size: 201 KiB |
BIN
IceCubesApp/Assets.xcassets/AppIcon.appiconset/Icon-512.png
Normal file
After Width: | Height: | Size: 201 KiB |
BIN
IceCubesApp/Assets.xcassets/AppIcon.appiconset/Icon-64.png
Normal file
After Width: | Height: | Size: 5.2 KiB |
|
@ -18,6 +18,8 @@
|
|||
</array>
|
||||
<key>com.apple.security.files.user-selected.read-only</key>
|
||||
<true/>
|
||||
<key>com.apple.security.network.client</key>
|
||||
<true/>
|
||||
<key>keychain-access-groups</key>
|
||||
<array>
|
||||
<string>$(AppIdentifierPrefix)$(BUNDLE_ID_PREFIX).IceCubesApp</string>
|
||||
|
|
|
@ -2,10 +2,14 @@
|
|||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>com.apple.security.app-sandbox</key>
|
||||
<true/>
|
||||
<key>com.apple.security.application-groups</key>
|
||||
<array>
|
||||
<string>group.$(BUNDLE_ID_PREFIX).IceCubesApp</string>
|
||||
</array>
|
||||
<key>com.apple.security.network.client</key>
|
||||
<true/>
|
||||
<key>keychain-access-groups</key>
|
||||
<array>
|
||||
<string>$(AppIdentifierPrefix)$(BUNDLE_ID_PREFIX).IceCubesApp</string>
|
||||
|
|
|
@ -2,10 +2,14 @@
|
|||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>com.apple.security.app-sandbox</key>
|
||||
<true/>
|
||||
<key>com.apple.security.application-groups</key>
|
||||
<array>
|
||||
<string>group.$(BUNDLE_ID_PREFIX).IceCubesApp</string>
|
||||
</array>
|
||||
<key>com.apple.security.network.client</key>
|
||||
<true/>
|
||||
<key>keychain-access-groups</key>
|
||||
<array>
|
||||
<string>$(AppIdentifierPrefix)$(BUNDLE_ID_PREFIX).IceCubesApp</string>
|
||||
|
|
|
@ -7,6 +7,6 @@ public extension CGFloat {
|
|||
static let scrollToViewHeight: CGFloat = 1
|
||||
static let statusColumnsSpacing: CGFloat = 8
|
||||
static let secondaryColumnWidth: CGFloat = 400
|
||||
static let sidebarWidth: CGFloat = 80
|
||||
static let sidebarWidth: CGFloat = 90
|
||||
static let pollBarHeight: CGFloat = 30
|
||||
}
|
||||
|
|
|
@ -12,7 +12,7 @@ public extension Font {
|
|||
private static let subheadline = onMac ? 16.0 : 15.0
|
||||
private static let footnote = onMac ? 15.0 : 13.0
|
||||
private static let caption = onMac ? 14.0 : 12.0
|
||||
private static let onMac = ProcessInfo.processInfo.isiOSAppOnMac
|
||||
private static let onMac = ProcessInfo.processInfo.isMacCatalystApp
|
||||
|
||||
private static func customFont(size: CGFloat, relativeTo textStyle: TextStyle) -> Font {
|
||||
if let chosenFont = Theme.shared.chosenFont {
|
||||
|
|
|
@ -14,5 +14,12 @@ import UIKit
|
|||
{
|
||||
guard let windowScene = scene as? UIWindowScene else { return }
|
||||
window = windowScene.keyWindow
|
||||
|
||||
#if targetEnvironment(macCatalyst)
|
||||
if let titlebar = windowScene.titlebar {
|
||||
titlebar.titleVisibility = .hidden
|
||||
titlebar.toolbar = nil
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,7 +16,7 @@ public struct AvatarView: View {
|
|||
case .account:
|
||||
return .init(width: 80, height: 80)
|
||||
case .status:
|
||||
if ProcessInfo.processInfo.isiOSAppOnMac {
|
||||
if ProcessInfo.processInfo.isMacCatalystApp {
|
||||
return .init(width: 48, height: 48)
|
||||
}
|
||||
return .init(width: 40, height: 40)
|
||||
|
|
|
@ -4,26 +4,15 @@ import SwiftUI
|
|||
|
||||
@MainActor
|
||||
public extension View {
|
||||
func statusEditorToolbarItem(routerPath: RouterPath, visibility: Models.Visibility) -> some ToolbarContent {
|
||||
ToolbarItem(placement: .navigationBarTrailing) {
|
||||
Button {
|
||||
routerPath.presentedSheet = .newStatusEditor(visibility: visibility)
|
||||
HapticManager.shared.fireHaptic(of: .buttonPress)
|
||||
} label: {
|
||||
Image(systemName: "square.and.pencil")
|
||||
.accessibilityLabel("accessibility.tabs.timeline.new-post.label")
|
||||
.accessibilityInputLabels([
|
||||
LocalizedStringKey("accessibility.tabs.timeline.new-post.label"),
|
||||
LocalizedStringKey("accessibility.tabs.timeline.new-post.inputLabel1"),
|
||||
LocalizedStringKey("accessibility.tabs.timeline.new-post.inputLabel2"),
|
||||
])
|
||||
}
|
||||
}
|
||||
func statusEditorToolbarItem(routerPath: RouterPath,
|
||||
visibility: Models.Visibility) -> some ToolbarContent {
|
||||
StatusEditorToolbarItem(visibility: visibility)
|
||||
}
|
||||
}
|
||||
|
||||
@MainActor
|
||||
public struct StatusEditorToolbarItem: ToolbarContent {
|
||||
@Environment(\.openWindow) private var openWindow
|
||||
@Environment(RouterPath.self) private var routerPath
|
||||
|
||||
let visibility: Models.Visibility
|
||||
|
@ -36,8 +25,12 @@ public struct StatusEditorToolbarItem: ToolbarContent {
|
|||
ToolbarItem(placement: .navigationBarTrailing) {
|
||||
Button {
|
||||
Task { @MainActor in
|
||||
routerPath.presentedSheet = .newStatusEditor(visibility: visibility)
|
||||
HapticManager.shared.fireHaptic(of: .buttonPress)
|
||||
if ProcessInfo.processInfo.isMacCatalystApp {
|
||||
openWindow(value: WindowDestination.newStatusEditor(visibility: visibility))
|
||||
} else {
|
||||
routerPath.presentedSheet = .newStatusEditor(visibility: visibility)
|
||||
HapticManager.shared.fireHaptic(of: .buttonPress)
|
||||
}
|
||||
}
|
||||
} label: {
|
||||
Image(systemName: "square.and.pencil")
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
import Combine
|
||||
@preconcurrency import SwiftUI
|
||||
import Models
|
||||
import QuickLook
|
||||
|
||||
|
@ -8,88 +7,10 @@ import QuickLook
|
|||
public var selectedMediaAttachment: MediaAttachment?
|
||||
public var mediaAttachments: [MediaAttachment] = []
|
||||
|
||||
public var url: URL? {
|
||||
didSet {
|
||||
if url == nil {
|
||||
cleanup(urls: urls)
|
||||
}
|
||||
}
|
||||
}
|
||||
public private(set) var urls: [URL] = []
|
||||
|
||||
|
||||
public init() {}
|
||||
|
||||
public func prepareFor(selectedMediaAttachment: MediaAttachment, mediaAttachments: [MediaAttachment]) {
|
||||
if ProcessInfo.processInfo.isiOSAppOnMac, let selectedURL = selectedMediaAttachment.url {
|
||||
let urls = mediaAttachments.compactMap{ $0.url }
|
||||
Task {
|
||||
await prepareFor(urls: urls, selectedURL: selectedURL)
|
||||
}
|
||||
} else {
|
||||
self.selectedMediaAttachment = selectedMediaAttachment
|
||||
self.mediaAttachments = mediaAttachments
|
||||
}
|
||||
}
|
||||
|
||||
private func prepareFor(urls: [URL], selectedURL: URL) async {
|
||||
var transaction = Transaction(animation: .default)
|
||||
transaction.disablesAnimations = true
|
||||
do {
|
||||
var order = 0
|
||||
let pathOrderMap = urls.reduce(into: [String: Int]()) { result, url in
|
||||
result[url.lastPathComponent] = order
|
||||
order += 1
|
||||
}
|
||||
let paths: [URL] = try await withThrowingTaskGroup(of: URL.self, body: { group in
|
||||
var paths: [URL] = []
|
||||
for url in urls {
|
||||
group.addTask {
|
||||
try await self.localPathFor(url: url)
|
||||
}
|
||||
}
|
||||
for try await path in group {
|
||||
paths.append(path)
|
||||
}
|
||||
return paths.sorted { url1, url2 in
|
||||
pathOrderMap[url1.lastPathComponent] ?? 0 < pathOrderMap[url2.lastPathComponent] ?? 0
|
||||
}
|
||||
})
|
||||
withTransaction(transaction) {
|
||||
self.urls = paths
|
||||
url = paths.first(where: { $0.lastPathComponent == selectedURL.lastPathComponent })
|
||||
}
|
||||
} catch {
|
||||
withTransaction(transaction) {
|
||||
self.urls = []
|
||||
url = nil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private var quickLookDir: URL {
|
||||
try! FileManager.default.url(for: .cachesDirectory,
|
||||
in: .userDomainMask,
|
||||
appropriateFor: nil,
|
||||
create: false)
|
||||
.appending(component: "quicklook")
|
||||
}
|
||||
|
||||
private func localPathFor(url: URL) async throws -> URL {
|
||||
try? FileManager.default.createDirectory(at: quickLookDir, withIntermediateDirectories: true)
|
||||
let path = quickLookDir.appendingPathComponent(url.lastPathComponent)
|
||||
|
||||
// Warning: Non-sendable type '(any URLSessionTaskDelegate)?' exiting main actor-isolated
|
||||
// context in call to non-isolated instance method 'data(for:delegate:)' cannot cross actor
|
||||
// boundary.
|
||||
// This is on the defaulted-to-nil second parameter of `.data(from:delegate:)`.
|
||||
// There is a Radar tracking this & others like it.
|
||||
let data = try await URLSession.shared.data(from: url).0
|
||||
try data.write(to: path)
|
||||
return path
|
||||
}
|
||||
|
||||
private func cleanup(urls _: [URL]) {
|
||||
try? FileManager.default.removeItem(at: quickLookDir)
|
||||
self.selectedMediaAttachment = selectedMediaAttachment
|
||||
self.mediaAttachments = mediaAttachments
|
||||
}
|
||||
}
|
||||
|
|
|
@ -25,6 +25,20 @@ public enum RouterDestination: Hashable {
|
|||
case tagsList(tags: [Tag])
|
||||
}
|
||||
|
||||
public enum WindowDestination: Hashable, Codable {
|
||||
case newStatusEditor(visibility: Models.Visibility)
|
||||
case mediaViewer(attachments: [MediaAttachment], selectedAttachment: MediaAttachment)
|
||||
|
||||
var initialSize: CGSize {
|
||||
switch self {
|
||||
case .newStatusEditor:
|
||||
return .init(width: 500, height: 700)
|
||||
case .mediaViewer:
|
||||
return .init(width: 800, height: 600)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public enum SheetDestination: Identifiable {
|
||||
case newStatusEditor(visibility: Models.Visibility)
|
||||
case editStatusEditor(status: Status)
|
||||
|
|
|
@ -71,6 +71,7 @@ public struct MediaUIView: View, @unchecked Sendable {
|
|||
|
||||
@ToolbarContentBuilder
|
||||
private var toolbarView: some ToolbarContent {
|
||||
#if !targetEnvironment(macCatalyst)
|
||||
ToolbarItem(placement: .topBarLeading) {
|
||||
Button {
|
||||
dismiss()
|
||||
|
@ -78,6 +79,7 @@ public struct MediaUIView: View, @unchecked Sendable {
|
|||
Image(systemName: "xmark.circle")
|
||||
}
|
||||
}
|
||||
#endif
|
||||
ToolbarItem(placement: .topBarTrailing) {
|
||||
if let url = attachments.first(where: { $0.id == scrollToId})?.url {
|
||||
Button {
|
||||
|
|
|
@ -37,7 +37,7 @@ struct StatusEditorAccessoryView: View {
|
|||
} label: {
|
||||
Label("status.editor.photo-library", systemImage: "photo")
|
||||
}
|
||||
if !ProcessInfo.processInfo.isiOSAppOnMac {
|
||||
if !ProcessInfo.processInfo.isMacCatalystApp {
|
||||
Button {
|
||||
isCameraPickerPresented = true
|
||||
} label: {
|
||||
|
|
|
@ -215,7 +215,7 @@ public struct StatusEditorView: View {
|
|||
SoundEffectManager.shared.playSound(of: .tootSent)
|
||||
NotificationCenter.default.post(name: NotificationsName.shareSheetClose,
|
||||
object: nil)
|
||||
if !viewModel.mode.isInShareExtension, !preferences.requestedReview, !ProcessInfo.processInfo.isiOSAppOnMac {
|
||||
if !viewModel.mode.isInShareExtension, !preferences.requestedReview, !ProcessInfo.processInfo.isMacCatalystApp {
|
||||
if let scene = UIApplication.shared.connectedScenes.first(where: { $0.activationState == .foregroundActive }) as? UIWindowScene {
|
||||
SKStoreReviewController.requestReview(in: scene)
|
||||
}
|
||||
|
|
|
@ -45,7 +45,7 @@ extension TextView.Representable {
|
|||
textView.allowsEditingTextAttributes = false
|
||||
textView.returnKeyType = .default
|
||||
textView.allowsEditingTextAttributes = true
|
||||
if ProcessInfo.processInfo.isiOSAppOnMac {
|
||||
if ProcessInfo.processInfo.isMacCatalystApp {
|
||||
textView.inlinePredictionType = .no
|
||||
}
|
||||
|
||||
|
|
|
@ -9,6 +9,7 @@ import SwiftUI
|
|||
|
||||
@MainActor
|
||||
public struct StatusRowView: View {
|
||||
@Environment(\.openWindow) private var openWindow
|
||||
@Environment(\.isInCaptureMode) private var isInCaptureMode: Bool
|
||||
@Environment(\.redactionReasons) private var reasons
|
||||
@Environment(\.isCompact) private var isCompact: Bool
|
||||
|
@ -208,7 +209,12 @@ public struct StatusRowView: View {
|
|||
Button("accessibility.status.media-viewer-action.label") {
|
||||
HapticManager.shared.fireHaptic(of: .notification(.success))
|
||||
let attachments = viewModel.finalStatus.mediaAttachments
|
||||
quickLook.prepareFor(selectedMediaAttachment: attachments[0], mediaAttachments: attachments)
|
||||
if ProcessInfo.processInfo.isMacCatalystApp {
|
||||
openWindow(value: WindowDestination.mediaViewer(attachments: attachments,
|
||||
selectedAttachment: attachments[0]))
|
||||
} else {
|
||||
quickLook.prepareFor(selectedMediaAttachment: attachments[0], mediaAttachments: attachments)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -8,6 +8,7 @@ import MediaUI
|
|||
|
||||
@MainActor
|
||||
public struct StatusRowMediaPreviewView: View {
|
||||
@Environment(\.openWindow) private var openWindow
|
||||
@Environment(\.isSecondaryColumn) private var isSecondaryColumn: Bool
|
||||
@Environment(\.extraLeadingInset) private var extraLeadingInset: CGFloat
|
||||
@Environment(\.isInCaptureMode) private var isInCaptureMode: Bool
|
||||
|
@ -88,7 +89,12 @@ public struct StatusRowMediaPreviewView: View {
|
|||
if attachments.count == 1, let attachment = attachments.first {
|
||||
makeFeaturedImagePreview(attachment: attachment)
|
||||
.onTapGesture {
|
||||
quickLook.prepareFor(selectedMediaAttachment: attachment, mediaAttachments: attachments)
|
||||
if ProcessInfo.processInfo.isMacCatalystApp {
|
||||
openWindow(value: WindowDestination.mediaViewer(attachments: attachments,
|
||||
selectedAttachment: attachment))
|
||||
} else {
|
||||
quickLook.prepareFor(selectedMediaAttachment: attachment, mediaAttachments: attachments)
|
||||
}
|
||||
}
|
||||
.accessibilityElement(children: .ignore)
|
||||
.accessibilityLabel(Self.accessibilityLabel(for: attachment))
|
||||
|
@ -272,7 +278,12 @@ public struct StatusRowMediaPreviewView: View {
|
|||
// #965: do not create overlapping tappable areas, when multiple images are shown
|
||||
.contentShape(Rectangle())
|
||||
.onTapGesture {
|
||||
quickLook.prepareFor(selectedMediaAttachment: attachment, mediaAttachments: attachments)
|
||||
if ProcessInfo.processInfo.isMacCatalystApp {
|
||||
openWindow(value: WindowDestination.mediaViewer(attachments: attachments,
|
||||
selectedAttachment: attachment))
|
||||
} else {
|
||||
quickLook.prepareFor(selectedMediaAttachment: attachment, mediaAttachments: attachments)
|
||||
}
|
||||
}
|
||||
.accessibilityElement(children: .ignore)
|
||||
.accessibilityLabel(Self.accessibilityLabel(for: attachment))
|
||||
|
|