mirror of
https://github.com/Dimillian/IceCubesApp.git
synced 2024-11-25 09:41:02 +00:00
macOS / iPad app fixes + support drop in the editor + global new post button
This commit is contained in:
parent
7f6419ebae
commit
899ccd8ad7
9 changed files with 174 additions and 44 deletions
|
@ -34,6 +34,7 @@
|
||||||
9F398AA92935FFDB00A889F2 /* Account in Frameworks */ = {isa = PBXBuildFile; productRef = 9F398AA82935FFDB00A889F2 /* Account */; };
|
9F398AA92935FFDB00A889F2 /* Account in Frameworks */ = {isa = PBXBuildFile; productRef = 9F398AA82935FFDB00A889F2 /* Account */; };
|
||||||
9F398AAB2935FFDB00A889F2 /* Models in Frameworks */ = {isa = PBXBuildFile; productRef = 9F398AAA2935FFDB00A889F2 /* Models */; };
|
9F398AAB2935FFDB00A889F2 /* Models in Frameworks */ = {isa = PBXBuildFile; productRef = 9F398AAA2935FFDB00A889F2 /* Models */; };
|
||||||
9F398AB329360A4C00A889F2 /* TimelineTab.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9F398AB229360A4C00A889F2 /* TimelineTab.swift */; };
|
9F398AB329360A4C00A889F2 /* TimelineTab.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9F398AB229360A4C00A889F2 /* TimelineTab.swift */; };
|
||||||
|
9F4A48192976B21900A1A038 /* ProfileTab.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9F4A48182976B21900A1A038 /* ProfileTab.swift */; };
|
||||||
9F55C68D2955968700F94077 /* ExploreTab.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9F55C68C2955968700F94077 /* ExploreTab.swift */; };
|
9F55C68D2955968700F94077 /* ExploreTab.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9F55C68C2955968700F94077 /* ExploreTab.swift */; };
|
||||||
9F55C6902955993C00F94077 /* Explore in Frameworks */ = {isa = PBXBuildFile; productRef = 9F55C68F2955993C00F94077 /* Explore */; };
|
9F55C6902955993C00F94077 /* Explore in Frameworks */ = {isa = PBXBuildFile; productRef = 9F55C68F2955993C00F94077 /* Explore */; };
|
||||||
9F5E581929545BE700A53960 /* Env in Frameworks */ = {isa = PBXBuildFile; productRef = 9F5E581829545BE700A53960 /* Env */; };
|
9F5E581929545BE700A53960 /* Env in Frameworks */ = {isa = PBXBuildFile; productRef = 9F5E581829545BE700A53960 /* Env */; };
|
||||||
|
@ -125,6 +126,7 @@
|
||||||
9F398AA52935FE8A00A889F2 /* AppRouteur.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppRouteur.swift; sourceTree = "<group>"; };
|
9F398AA52935FE8A00A889F2 /* AppRouteur.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppRouteur.swift; sourceTree = "<group>"; };
|
||||||
9F398AAC2936005300A889F2 /* Account */ = {isa = PBXFileReference; lastKnownFileType = wrapper; name = Account; path = Packages/Account; sourceTree = "<group>"; };
|
9F398AAC2936005300A889F2 /* Account */ = {isa = PBXFileReference; lastKnownFileType = wrapper; name = Account; path = Packages/Account; sourceTree = "<group>"; };
|
||||||
9F398AB229360A4C00A889F2 /* TimelineTab.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimelineTab.swift; sourceTree = "<group>"; };
|
9F398AB229360A4C00A889F2 /* TimelineTab.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimelineTab.swift; sourceTree = "<group>"; };
|
||||||
|
9F4A48182976B21900A1A038 /* ProfileTab.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProfileTab.swift; sourceTree = "<group>"; };
|
||||||
9F55C68C2955968700F94077 /* ExploreTab.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ExploreTab.swift; sourceTree = "<group>"; };
|
9F55C68C2955968700F94077 /* ExploreTab.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ExploreTab.swift; sourceTree = "<group>"; };
|
||||||
9F55C68E295598F900F94077 /* Explore */ = {isa = PBXFileReference; lastKnownFileType = wrapper; name = Explore; path = Packages/Explore; sourceTree = "<group>"; };
|
9F55C68E295598F900F94077 /* Explore */ = {isa = PBXFileReference; lastKnownFileType = wrapper; name = Explore; path = Packages/Explore; sourceTree = "<group>"; };
|
||||||
9F5E581729545B5500A53960 /* Env */ = {isa = PBXFileReference; lastKnownFileType = wrapper; name = Env; path = Packages/Env; sourceTree = "<group>"; };
|
9F5E581729545B5500A53960 /* Env */ = {isa = PBXFileReference; lastKnownFileType = wrapper; name = Env; path = Packages/Env; sourceTree = "<group>"; };
|
||||||
|
@ -267,6 +269,7 @@
|
||||||
9F35DB4B2952005C00B3281A /* MessagesTab.swift */,
|
9F35DB4B2952005C00B3281A /* MessagesTab.swift */,
|
||||||
9F55C68C2955968700F94077 /* ExploreTab.swift */,
|
9F55C68C2955968700F94077 /* ExploreTab.swift */,
|
||||||
9F2B92F5295AE04800DE16D0 /* Tabs.swift */,
|
9F2B92F5295AE04800DE16D0 /* Tabs.swift */,
|
||||||
|
9F4A48182976B21900A1A038 /* ProfileTab.swift */,
|
||||||
);
|
);
|
||||||
path = Tabs;
|
path = Tabs;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
|
@ -537,6 +540,7 @@
|
||||||
9F398AB329360A4C00A889F2 /* TimelineTab.swift in Sources */,
|
9F398AB329360A4C00A889F2 /* TimelineTab.swift in Sources */,
|
||||||
9F398AA62935FE8A00A889F2 /* AppRouteur.swift in Sources */,
|
9F398AA62935FE8A00A889F2 /* AppRouteur.swift in Sources */,
|
||||||
9FBFE63D292A715500C250E9 /* IceCubesApp.swift in Sources */,
|
9FBFE63D292A715500C250E9 /* IceCubesApp.swift in Sources */,
|
||||||
|
9F4A48192976B21900A1A038 /* ProfileTab.swift in Sources */,
|
||||||
9F2B92FA295DA7D700DE16D0 /* AddAccountsView.swift in Sources */,
|
9F2B92FA295DA7D700DE16D0 /* AddAccountsView.swift in Sources */,
|
||||||
639CDF9C296AC82F00C35E58 /* SafariRouteur.swift in Sources */,
|
639CDF9C296AC82F00C35E58 /* SafariRouteur.swift in Sources */,
|
||||||
9F35DB4729506F6600B3281A /* NotificationTab.swift in Sources */,
|
9F35DB4729506F6600B3281A /* NotificationTab.swift in Sources */,
|
||||||
|
|
|
@ -21,12 +21,13 @@ struct IceCubesApp: App {
|
||||||
@StateObject private var watcher = StreamWatcher()
|
@StateObject private var watcher = StreamWatcher()
|
||||||
@StateObject private var quickLook = QuickLook()
|
@StateObject private var quickLook = QuickLook()
|
||||||
@StateObject private var theme = Theme.shared
|
@StateObject private var theme = Theme.shared
|
||||||
|
@StateObject private var sidebarRouterPath = RouterPath()
|
||||||
|
|
||||||
@State private var selectedTab: Tab = .timeline
|
@State private var selectedTab: Tab = .timeline
|
||||||
@State private var selectSidebarItem: Tab? = .timeline
|
@State private var selectSidebarItem: Tab? = .timeline
|
||||||
@State private var popToRootTab: Tab = .other
|
@State private var popToRootTab: Tab = .other
|
||||||
@State private var sideBarLoadedTabs: [Tab] = []
|
@State private var sideBarLoadedTabs: Set<Tab> = Set()
|
||||||
|
|
||||||
private var availableTabs: [Tab] {
|
private var availableTabs: [Tab] {
|
||||||
appAccountsManager.currentClient.isAuth ? Tab.loggedInTabs() : Tab.loggedOutTab()
|
appAccountsManager.currentClient.isAuth ? Tab.loggedInTabs() : Tab.loggedOutTab()
|
||||||
}
|
}
|
||||||
|
@ -54,6 +55,14 @@ struct IceCubesApp: App {
|
||||||
.edgesIgnoringSafeArea(.bottom)
|
.edgesIgnoringSafeArea(.bottom)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
.commands {
|
||||||
|
CommandGroup(replacing: CommandGroupPlacement.newItem) {
|
||||||
|
Button("New post") {
|
||||||
|
sidebarRouterPath.presentedSheet = .newStatusEditor(visibility: userPreferences.serverPreferences?.postVisibility ?? .pub)
|
||||||
|
}
|
||||||
|
.keyboardShortcut("n", modifiers: .command)
|
||||||
|
}
|
||||||
|
}
|
||||||
.onChange(of: scenePhase) { scenePhase in
|
.onChange(of: scenePhase) { scenePhase in
|
||||||
handleScenePhase(scenePhase: scenePhase)
|
handleScenePhase(scenePhase: scenePhase)
|
||||||
}
|
}
|
||||||
|
@ -84,10 +93,11 @@ struct IceCubesApp: App {
|
||||||
private var sidebarView: some View {
|
private var sidebarView: some View {
|
||||||
SideBarView(selectedTab: $selectedTab,
|
SideBarView(selectedTab: $selectedTab,
|
||||||
popToRootTab: $popToRootTab,
|
popToRootTab: $popToRootTab,
|
||||||
tabs: availableTabs) {
|
tabs: availableTabs,
|
||||||
|
routerPath: sidebarRouterPath) {
|
||||||
ZStack {
|
ZStack {
|
||||||
if let account = currentAccount.account, selectedTab == .profile {
|
if selectedTab == .profile {
|
||||||
AccountDetailView(account: account)
|
ProfileTab(popToRootTab: $popToRootTab)
|
||||||
}
|
}
|
||||||
ForEach(availableTabs) { tab in
|
ForEach(availableTabs) { tab in
|
||||||
if tab == selectedTab || sideBarLoadedTabs.contains(tab) {
|
if tab == selectedTab || sideBarLoadedTabs.contains(tab) {
|
||||||
|
@ -96,9 +106,7 @@ struct IceCubesApp: App {
|
||||||
.opacity(tab == selectedTab ? 1 : 0)
|
.opacity(tab == selectedTab ? 1 : 0)
|
||||||
.id(tab)
|
.id(tab)
|
||||||
.onAppear {
|
.onAppear {
|
||||||
if !sideBarLoadedTabs.contains(tab) {
|
sideBarLoadedTabs.insert(tab)
|
||||||
sideBarLoadedTabs.append(tab)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
EmptyView()
|
EmptyView()
|
||||||
|
@ -186,4 +194,5 @@ class AppDelegate: NSObject, UIApplicationDelegate {
|
||||||
}
|
}
|
||||||
|
|
||||||
func application(_: UIApplication, didFailToRegisterForRemoteNotificationsWithError _: Error) {}
|
func application(_: UIApplication, didFailToRegisterForRemoteNotificationsWithError _: Error) {}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -56,12 +56,9 @@ class AppQLPreviewCpntroller: QLPreviewController {
|
||||||
|
|
||||||
override func viewDidLoad() {
|
override func viewDidLoad() {
|
||||||
super.viewDidLoad()
|
super.viewDidLoad()
|
||||||
navigationItem.rightBarButtonItem = closeButton
|
if UIDevice.current.userInterfaceIdiom != .pad {
|
||||||
}
|
navigationItem.rightBarButtonItem = closeButton
|
||||||
|
}
|
||||||
override func viewDidAppear(_ animated: Bool) {
|
|
||||||
super.viewDidAppear(animated)
|
|
||||||
navigationItem.rightBarButtonItem = closeButton
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override func viewDidLayoutSubviews() {
|
override func viewDidLayoutSubviews() {
|
||||||
|
|
|
@ -7,51 +7,106 @@ import SwiftUI
|
||||||
struct SideBarView<Content: View>: View {
|
struct SideBarView<Content: View>: View {
|
||||||
@EnvironmentObject private var currentAccount: CurrentAccount
|
@EnvironmentObject private var currentAccount: CurrentAccount
|
||||||
@EnvironmentObject private var theme: Theme
|
@EnvironmentObject private var theme: Theme
|
||||||
|
@EnvironmentObject private var watcher: StreamWatcher
|
||||||
|
@EnvironmentObject private var userPreferences: UserPreferences
|
||||||
|
|
||||||
@Binding var selectedTab: Tab
|
@Binding var selectedTab: Tab
|
||||||
@Binding var popToRootTab: Tab
|
@Binding var popToRootTab: Tab
|
||||||
var tabs: [Tab]
|
var tabs: [Tab]
|
||||||
|
@ObservedObject var routerPath = RouterPath()
|
||||||
@ViewBuilder var content: () -> Content
|
@ViewBuilder var content: () -> Content
|
||||||
|
|
||||||
|
private func badgeFor(tab: Tab) -> Int {
|
||||||
|
if tab == .notifications && selectedTab != tab {
|
||||||
|
return watcher.unreadNotificationsCount + userPreferences.pushNotificationsCount
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
private var profileView: some View {
|
||||||
|
Button {
|
||||||
|
selectedTab = .profile
|
||||||
|
} label: {
|
||||||
|
AppAccountsSelectorView(routeurPath: RouterPath(),
|
||||||
|
accountCreationEnabled: false,
|
||||||
|
avatarSize: .status)
|
||||||
|
}
|
||||||
|
.frame(width: .sidebarWidth, height: 60)
|
||||||
|
.background(selectedTab == .profile ? theme.secondaryBackgroundColor : .clear)
|
||||||
|
}
|
||||||
|
|
||||||
|
private func makeIconForTab(tab: Tab) -> some View {
|
||||||
|
ZStack(alignment: .topTrailing) {
|
||||||
|
Image(systemName: tab.iconName)
|
||||||
|
.resizable()
|
||||||
|
.aspectRatio(contentMode: .fit)
|
||||||
|
.frame(width: 24, height: 24)
|
||||||
|
.foregroundColor(tab == selectedTab ? theme.tintColor : .gray)
|
||||||
|
if let badge = badgeFor(tab: tab), badge > 0 {
|
||||||
|
ZStack {
|
||||||
|
Circle()
|
||||||
|
.fill(.red)
|
||||||
|
Text(String(badge))
|
||||||
|
.foregroundColor(.white)
|
||||||
|
.font(.footnote)
|
||||||
|
}
|
||||||
|
.frame(width: 20, height: 20)
|
||||||
|
.offset(x: 10, y: -10)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.contentShape(Rectangle())
|
||||||
|
.frame(width: .sidebarWidth, height: 50)
|
||||||
|
}
|
||||||
|
|
||||||
|
private var postButton: some View {
|
||||||
|
Button {
|
||||||
|
routerPath.presentedSheet = .newStatusEditor(visibility: userPreferences.serverPreferences?.postVisibility ?? .pub)
|
||||||
|
} label: {
|
||||||
|
Image(systemName: "square.and.pencil")
|
||||||
|
.resizable()
|
||||||
|
.aspectRatio(contentMode: .fit)
|
||||||
|
.frame(width: 20, height: 30)
|
||||||
|
}
|
||||||
|
.buttonStyle(.borderedProminent)
|
||||||
|
.keyboardShortcut("n", modifiers: .command)
|
||||||
|
}
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
HStack(spacing: 0) {
|
HStack(spacing: 0) {
|
||||||
VStack(alignment: .center) {
|
ScrollView {
|
||||||
Button {
|
VStack(alignment: .center) {
|
||||||
selectedTab = .profile
|
profileView
|
||||||
} label: {
|
ForEach(tabs) { tab in
|
||||||
AppAccountsSelectorView(routeurPath: RouterPath(),
|
Button {
|
||||||
accountCreationEnabled: false,
|
if tab == selectedTab {
|
||||||
avatarSize: .status)
|
popToRootTab = .other
|
||||||
}
|
DispatchQueue.main.asyncAfter(deadline: .now() + 0.01) {
|
||||||
.frame(width: 80, height: 60)
|
popToRootTab = tab
|
||||||
.background(selectedTab == .profile ? theme.secondaryBackgroundColor : .clear)
|
}
|
||||||
ForEach(tabs) { tab in
|
|
||||||
Button {
|
|
||||||
if tab == selectedTab {
|
|
||||||
popToRootTab = .other
|
|
||||||
DispatchQueue.main.asyncAfter(deadline: .now() + 0.01) {
|
|
||||||
popToRootTab = tab
|
|
||||||
}
|
}
|
||||||
|
selectedTab = tab
|
||||||
|
if tab == .notifications {
|
||||||
|
watcher.unreadNotificationsCount = 0
|
||||||
|
userPreferences.pushNotificationsCount = 0
|
||||||
|
}
|
||||||
|
} label: {
|
||||||
|
makeIconForTab(tab: tab)
|
||||||
}
|
}
|
||||||
selectedTab = tab
|
.background(tab == selectedTab ? theme.secondaryBackgroundColor : .clear)
|
||||||
} label: {
|
|
||||||
Image(systemName: tab.iconName)
|
|
||||||
.resizable()
|
|
||||||
.aspectRatio(contentMode: .fit)
|
|
||||||
.frame(width: 24, height: 24)
|
|
||||||
.foregroundColor(tab == selectedTab ? theme.tintColor : .gray)
|
|
||||||
}
|
}
|
||||||
.frame(width: 80, height: 50)
|
postButton
|
||||||
.background(tab == selectedTab ? theme.secondaryBackgroundColor : .clear)
|
.padding(.top, 12)
|
||||||
|
Spacer()
|
||||||
}
|
}
|
||||||
Spacer()
|
|
||||||
}
|
}
|
||||||
.frame(width: 80)
|
.frame(width: .sidebarWidth)
|
||||||
.background(.clear)
|
.scrollContentBackground(.hidden)
|
||||||
|
.background(.thinMaterial)
|
||||||
Divider()
|
Divider()
|
||||||
.edgesIgnoringSafeArea(.top)
|
.edgesIgnoringSafeArea(.top)
|
||||||
content()
|
content()
|
||||||
}
|
}
|
||||||
.background(.thinMaterial)
|
.background(.thinMaterial)
|
||||||
|
.withSheetDestinations(sheetDestinations: $routerPath.presentedSheet)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
50
IceCubesApp/App/Tabs/ProfileTab.swift
Normal file
50
IceCubesApp/App/Tabs/ProfileTab.swift
Normal file
|
@ -0,0 +1,50 @@
|
||||||
|
import Account
|
||||||
|
import AppAccount
|
||||||
|
import Conversations
|
||||||
|
import Env
|
||||||
|
import Models
|
||||||
|
import Network
|
||||||
|
import Shimmer
|
||||||
|
import SwiftUI
|
||||||
|
|
||||||
|
struct ProfileTab: View {
|
||||||
|
@EnvironmentObject private var client: Client
|
||||||
|
@EnvironmentObject private var currentAccount: CurrentAccount
|
||||||
|
@StateObject private var routeurPath = RouterPath()
|
||||||
|
@Binding var popToRootTab: Tab
|
||||||
|
|
||||||
|
var body: some View {
|
||||||
|
NavigationStack(path: $routeurPath.path) {
|
||||||
|
if let account = currentAccount.account {
|
||||||
|
AccountDetailView(account: account)
|
||||||
|
.withAppRouteur()
|
||||||
|
.withSheetDestinations(sheetDestinations: $routeurPath.presentedSheet)
|
||||||
|
.toolbar {
|
||||||
|
if UIDevice.current.userInterfaceIdiom != .pad {
|
||||||
|
ToolbarItem(placement: .navigationBarLeading) {
|
||||||
|
AppAccountsSelectorView(routeurPath: routeurPath)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.id(currentAccount.account?.id)
|
||||||
|
} else {
|
||||||
|
AccountDetailView(account: .placeholder())
|
||||||
|
.redacted(reason: .placeholder)
|
||||||
|
.shimmering()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.onChange(of: $popToRootTab.wrappedValue) { popToRootTab in
|
||||||
|
if popToRootTab == .messages {
|
||||||
|
routeurPath.path = []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.onChange(of: currentAccount.account?.id) { _ in
|
||||||
|
routeurPath.path = []
|
||||||
|
}
|
||||||
|
.onAppear {
|
||||||
|
routeurPath.client = client
|
||||||
|
}
|
||||||
|
.withSafariRouteur()
|
||||||
|
.environmentObject(routeurPath)
|
||||||
|
}
|
||||||
|
}
|
|
@ -5,4 +5,5 @@ public extension CGFloat {
|
||||||
static let dividerPadding: CGFloat = 2
|
static let dividerPadding: CGFloat = 2
|
||||||
static let statusColumnsSpacing: CGFloat = 8
|
static let statusColumnsSpacing: CGFloat = 8
|
||||||
static let maxColumnWidth: CGFloat = 650
|
static let maxColumnWidth: CGFloat = 650
|
||||||
|
static let sidebarWidth: CGFloat = 80
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
import Foundation
|
import Foundation
|
||||||
import UIKit
|
import UIKit
|
||||||
|
import UniformTypeIdentifiers
|
||||||
|
|
||||||
@MainActor
|
@MainActor
|
||||||
enum StatusEditorUTTypeSupported: String, CaseIterable {
|
enum StatusEditorUTTypeSupported: String, CaseIterable {
|
||||||
|
@ -9,6 +10,10 @@ enum StatusEditorUTTypeSupported: String, CaseIterable {
|
||||||
case image = "public.image"
|
case image = "public.image"
|
||||||
case jpeg = "public.jpeg"
|
case jpeg = "public.jpeg"
|
||||||
case png = "public.png"
|
case png = "public.png"
|
||||||
|
|
||||||
|
static func types() -> [UTType] {
|
||||||
|
[.url, .text, .plainText, .image, .jpeg, .png]
|
||||||
|
}
|
||||||
|
|
||||||
func loadItemContent(item: NSItemProvider) async throws -> Any? {
|
func loadItemContent(item: NSItemProvider) async throws -> Any? {
|
||||||
let result = try await item.loadItem(forTypeIdentifier: rawValue)
|
let result = try await item.loadItem(forTypeIdentifier: rawValue)
|
||||||
|
|
|
@ -67,6 +67,7 @@ public struct StatusEditorView: View {
|
||||||
viewModel: viewModel)
|
viewModel: viewModel)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
.onDrop(of: StatusEditorUTTypeSupported.types(), delegate: viewModel)
|
||||||
.onAppear {
|
.onAppear {
|
||||||
viewModel.client = client
|
viewModel.client = client
|
||||||
viewModel.currentAccount = currentAccount.account
|
viewModel.currentAccount = currentAccount.account
|
||||||
|
|
|
@ -238,7 +238,7 @@ public class StatusEditorViewModel: ObservableObject {
|
||||||
|
|
||||||
for range in urlRanges {
|
for range in urlRanges {
|
||||||
statusText.addAttributes([.foregroundColor: UIColor(theme?.tintColor ?? .brand),
|
statusText.addAttributes([.foregroundColor: UIColor(theme?.tintColor ?? .brand),
|
||||||
.underlineStyle: NSUnderlineStyle.single,
|
.underlineStyle: NSUnderlineStyle.single.rawValue,
|
||||||
.underlineColor: UIColor(theme?.tintColor ?? .brand)],
|
.underlineColor: UIColor(theme?.tintColor ?? .brand)],
|
||||||
range: NSRange(location: range.location, length: range.length))
|
range: NSRange(location: range.location, length: range.length))
|
||||||
}
|
}
|
||||||
|
@ -451,3 +451,11 @@ public class StatusEditorViewModel: ObservableObject {
|
||||||
data: data)
|
data: data)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extension StatusEditorViewModel: DropDelegate {
|
||||||
|
public func performDrop(info: DropInfo) -> Bool {
|
||||||
|
let item = info.itemProviders(for: StatusEditorUTTypeSupported.types())
|
||||||
|
processItemsProvider(items: item)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue