mirror of
https://github.com/yattee/yattee.git
synced 2024-12-22 21:43:41 +00:00
Add recent documents to home on iOS
This commit is contained in:
parent
8ec06b0d59
commit
bc1571a746
@ -54,6 +54,19 @@ final class DocumentsModel: ObservableObject {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func recentDocuments(_ limit: Int = 10) -> [URL] {
|
||||||
|
guard let documentsDirectory else { return [] }
|
||||||
|
|
||||||
|
return Array(
|
||||||
|
contents(of: documentsDirectory)
|
||||||
|
.sorted {
|
||||||
|
((try? $0.resourceValues(forKeys: [.creationDateKey]).creationDate) ?? Date()) >
|
||||||
|
((try? $1.resourceValues(forKeys: [.creationDateKey]).creationDate) ?? Date())
|
||||||
|
}
|
||||||
|
.prefix(limit)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
func isDocument(_ video: Video) -> Bool {
|
func isDocument(_ video: Video) -> Bool {
|
||||||
guard video.isLocal, let url = video.localStream?.localURL, let url = replacePrivateVar(url) else { return false }
|
guard video.isLocal, let url = video.localStream?.localURL, let url = replacePrivateVar(url) else { return false }
|
||||||
return isDocument(url)
|
return isDocument(url)
|
||||||
|
@ -22,10 +22,13 @@ extension Defaults.Keys {
|
|||||||
static let enableReturnYouTubeDislike = Key<Bool>("enableReturnYouTubeDislike", default: false)
|
static let enableReturnYouTubeDislike = Key<Bool>("enableReturnYouTubeDislike", default: false)
|
||||||
|
|
||||||
static let showHome = Key<Bool>("showHome", default: true)
|
static let showHome = Key<Bool>("showHome", default: true)
|
||||||
static let showDocuments = Key<Bool>("showDocuments", default: true)
|
|
||||||
static let showOpenActionsInHome = Key<Bool>("showOpenActionsInHome", default: true)
|
static let showOpenActionsInHome = Key<Bool>("showOpenActionsInHome", default: true)
|
||||||
static let showOpenActionsToolbarItem = Key<Bool>("showOpenActionsToolbarItem", default: false)
|
static let showOpenActionsToolbarItem = Key<Bool>("showOpenActionsToolbarItem", default: false)
|
||||||
static let showFavoritesInHome = Key<Bool>("showFavoritesInHome", default: true)
|
static let showFavoritesInHome = Key<Bool>("showFavoritesInHome", default: true)
|
||||||
|
#if os(iOS)
|
||||||
|
static let showDocuments = Key<Bool>("showDocuments", default: false)
|
||||||
|
static let homeRecentDocumentsItems = Key<Int>("homeRecentDocumentsItems", default: 3)
|
||||||
|
#endif
|
||||||
static let homeHistoryItems = Key<Int>("homeHistoryItems", default: 10)
|
static let homeHistoryItems = Key<Int>("homeHistoryItems", default: 10)
|
||||||
static let favorites = Key<[FavoriteItem]>("favorites", default: [])
|
static let favorites = Key<[FavoriteItem]>("favorites", default: [])
|
||||||
|
|
||||||
|
@ -7,16 +7,7 @@ struct DocumentsView: View {
|
|||||||
BrowserPlayerControls {
|
BrowserPlayerControls {
|
||||||
ScrollView(.vertical, showsIndicators: false) {
|
ScrollView(.vertical, showsIndicators: false) {
|
||||||
if model.directoryContents.isEmpty {
|
if model.directoryContents.isEmpty {
|
||||||
VStack(alignment: .center, spacing: 20) {
|
NoDocumentsView()
|
||||||
HStack {
|
|
||||||
Image(systemName: "doc")
|
|
||||||
Text("No documents")
|
|
||||||
}
|
|
||||||
Text("Share files from Finder on a Mac\nor iTunes on Windows")
|
|
||||||
.multilineTextAlignment(.center)
|
|
||||||
}
|
|
||||||
.frame(maxWidth: .infinity)
|
|
||||||
.foregroundColor(.secondary)
|
|
||||||
} else {
|
} else {
|
||||||
ForEach(model.sortedDirectoryContents, id: \.absoluteString) { url in
|
ForEach(model.sortedDirectoryContents, id: \.absoluteString) { url in
|
||||||
let video = Video.local(model.replacePrivateVar(url) ?? url)
|
let video = Video.local(model.replacePrivateVar(url) ?? url)
|
||||||
|
22
Shared/Documents/NoDocumentsView.swift
Normal file
22
Shared/Documents/NoDocumentsView.swift
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
import SwiftUI
|
||||||
|
|
||||||
|
struct NoDocumentsView: View {
|
||||||
|
var body: some View {
|
||||||
|
VStack(alignment: .center, spacing: 20) {
|
||||||
|
HStack {
|
||||||
|
Image(systemName: "doc")
|
||||||
|
Text("No documents")
|
||||||
|
}
|
||||||
|
Text("Share files from Finder on a Mac\nor iTunes on Windows")
|
||||||
|
.multilineTextAlignment(.center)
|
||||||
|
}
|
||||||
|
.frame(maxWidth: .infinity)
|
||||||
|
.foregroundColor(.secondary)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct NoDocumentsView_Previews: PreviewProvider {
|
||||||
|
static var previews: some View {
|
||||||
|
NoDocumentsView()
|
||||||
|
}
|
||||||
|
}
|
36
Shared/Documents/RecentDocumentsView.swift
Normal file
36
Shared/Documents/RecentDocumentsView.swift
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
import Defaults
|
||||||
|
import SwiftUI
|
||||||
|
|
||||||
|
struct RecentDocumentsView: View {
|
||||||
|
var limit = 3
|
||||||
|
let model = DocumentsModel.shared
|
||||||
|
|
||||||
|
var body: some View {
|
||||||
|
LazyVStack {
|
||||||
|
if recentDocuments.isEmpty {
|
||||||
|
NoDocumentsView()
|
||||||
|
} else {
|
||||||
|
ForEach(recentDocuments, id: \.absoluteString) { url in
|
||||||
|
let video = Video.local(model.replacePrivateVar(url) ?? url)
|
||||||
|
PlayerQueueRow(
|
||||||
|
item: PlayerQueueItem(video)
|
||||||
|
)
|
||||||
|
.contextMenu {
|
||||||
|
VideoContextMenuView(video: video)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.padding(.horizontal, 15)
|
||||||
|
}
|
||||||
|
|
||||||
|
var recentDocuments: [URL] {
|
||||||
|
model.recentDocuments(limit)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct RecentDocumentsView_Previews: PreviewProvider {
|
||||||
|
static var previews: some View {
|
||||||
|
RecentDocumentsView()
|
||||||
|
}
|
||||||
|
}
|
@ -15,12 +15,18 @@ struct HomeView: View {
|
|||||||
@FetchRequest(sortDescriptors: [.init(key: "watchedAt", ascending: false)])
|
@FetchRequest(sortDescriptors: [.init(key: "watchedAt", ascending: false)])
|
||||||
var watches: FetchedResults<Watch>
|
var watches: FetchedResults<Watch>
|
||||||
@State private var historyID = UUID()
|
@State private var historyID = UUID()
|
||||||
|
#if os(iOS)
|
||||||
|
@State private var recentDocumentsID = UUID()
|
||||||
|
#endif
|
||||||
|
|
||||||
var favoritesObserver: Any?
|
var favoritesObserver: Any?
|
||||||
|
|
||||||
#if !os(tvOS)
|
#if !os(tvOS)
|
||||||
@Default(.favorites) private var favorites
|
@Default(.favorites) private var favorites
|
||||||
#endif
|
#endif
|
||||||
|
#if os(iOS)
|
||||||
|
@Default(.homeRecentDocumentsItems) private var homeRecentDocumentsItems
|
||||||
|
#endif
|
||||||
@Default(.homeHistoryItems) private var homeHistoryItems
|
@Default(.homeHistoryItems) private var homeHistoryItems
|
||||||
@Default(.showFavoritesInHome) private var showFavoritesInHome
|
@Default(.showFavoritesInHome) private var showFavoritesInHome
|
||||||
@Default(.showOpenActionsInHome) private var showOpenActionsInHome
|
@Default(.showOpenActionsInHome) private var showOpenActionsInHome
|
||||||
@ -87,10 +93,33 @@ struct HomeView: View {
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if homeRecentDocumentsItems > 0 {
|
||||||
|
VStack {
|
||||||
|
HStack {
|
||||||
|
sectionLabel("Recent Documents")
|
||||||
|
|
||||||
|
Spacer()
|
||||||
|
|
||||||
|
Button {
|
||||||
|
recentDocumentsID = UUID()
|
||||||
|
} label: {
|
||||||
|
Label("Refresh", systemImage: "arrow.clockwise")
|
||||||
|
.font(.headline)
|
||||||
|
.labelStyle(.iconOnly)
|
||||||
|
.foregroundColor(.secondary)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
RecentDocumentsView(limit: homeRecentDocumentsItems)
|
||||||
|
.id(recentDocumentsID)
|
||||||
|
}
|
||||||
|
.frame(maxWidth: .infinity, alignment: .leading)
|
||||||
|
}
|
||||||
|
|
||||||
if homeHistoryItems > 0 {
|
if homeHistoryItems > 0 {
|
||||||
VStack {
|
VStack {
|
||||||
HStack {
|
HStack {
|
||||||
Text("History")
|
sectionLabel("History")
|
||||||
Spacer()
|
Spacer()
|
||||||
Button {
|
Button {
|
||||||
navigation.presentAlert(
|
navigation.presentAlert(
|
||||||
@ -108,17 +137,11 @@ struct HomeView: View {
|
|||||||
Label("Clear History", systemImage: "trash")
|
Label("Clear History", systemImage: "trash")
|
||||||
.font(.headline)
|
.font(.headline)
|
||||||
.labelStyle(.iconOnly)
|
.labelStyle(.iconOnly)
|
||||||
|
.foregroundColor(.secondary)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#if os(tvOS)
|
|
||||||
.padding(.horizontal, 40)
|
|
||||||
#else
|
|
||||||
.padding(.horizontal, 15)
|
|
||||||
#endif
|
|
||||||
.font(.title3.bold())
|
|
||||||
.frame(maxWidth: .infinity, alignment: .leading)
|
.frame(maxWidth: .infinity, alignment: .leading)
|
||||||
.foregroundColor(.secondary)
|
|
||||||
|
|
||||||
HistoryView(limit: homeHistoryItems)
|
HistoryView(limit: homeHistoryItems)
|
||||||
.id(historyID)
|
.id(historyID)
|
||||||
@ -157,9 +180,21 @@ struct HomeView: View {
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func sectionLabel(_ label: String) -> some View {
|
||||||
|
Text(label)
|
||||||
|
#if os(tvOS)
|
||||||
|
.padding(.horizontal, 40)
|
||||||
|
#else
|
||||||
|
.padding(.horizontal, 15)
|
||||||
|
#endif
|
||||||
|
.font(.title3.bold())
|
||||||
|
.frame(maxWidth: .infinity, alignment: .leading)
|
||||||
|
.foregroundColor(.secondary)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Favorites_Previews: PreviewProvider {
|
struct Home_Previews: PreviewProvider {
|
||||||
static var previews: some View {
|
static var previews: some View {
|
||||||
TabView {
|
TabView {
|
||||||
HomeView()
|
HomeView()
|
||||||
|
@ -8,6 +8,7 @@ struct BrowsingSettings: View {
|
|||||||
#endif
|
#endif
|
||||||
@Default(.accountPickerDisplaysAnonymousAccounts) private var accountPickerDisplaysAnonymousAccounts
|
@Default(.accountPickerDisplaysAnonymousAccounts) private var accountPickerDisplaysAnonymousAccounts
|
||||||
#if os(iOS)
|
#if os(iOS)
|
||||||
|
@Default(.homeRecentDocumentsItems) private var homeRecentDocumentsItems
|
||||||
@Default(.lockPortraitWhenBrowsing) private var lockPortraitWhenBrowsing
|
@Default(.lockPortraitWhenBrowsing) private var lockPortraitWhenBrowsing
|
||||||
#endif
|
#endif
|
||||||
@Default(.thumbnailsQuality) private var thumbnailsQuality
|
@Default(.thumbnailsQuality) private var thumbnailsQuality
|
||||||
@ -24,6 +25,9 @@ struct BrowsingSettings: View {
|
|||||||
@EnvironmentObject<AccountsModel> private var accounts
|
@EnvironmentObject<AccountsModel> private var accounts
|
||||||
|
|
||||||
@State private var homeHistoryItemsText = ""
|
@State private var homeHistoryItemsText = ""
|
||||||
|
#if os(iOS)
|
||||||
|
@State private var homeRecentDocumentsItemsText = ""
|
||||||
|
#endif
|
||||||
#if os(macOS)
|
#if os(macOS)
|
||||||
@State private var presentingEditFavoritesSheet = false
|
@State private var presentingEditFavoritesSheet = false
|
||||||
#endif
|
#endif
|
||||||
@ -87,6 +91,22 @@ struct BrowsingSettings: View {
|
|||||||
}
|
}
|
||||||
.multilineTextAlignment(.trailing)
|
.multilineTextAlignment(.trailing)
|
||||||
|
|
||||||
|
HStack {
|
||||||
|
Text("Recent documents")
|
||||||
|
TextField("Recent documents", text: $homeRecentDocumentsItemsText)
|
||||||
|
.labelsHidden()
|
||||||
|
#if !os(macOS)
|
||||||
|
.keyboardType(.numberPad)
|
||||||
|
#endif
|
||||||
|
.onAppear {
|
||||||
|
homeRecentDocumentsItemsText = String(homeRecentDocumentsItems)
|
||||||
|
}
|
||||||
|
.onChange(of: homeRecentDocumentsItemsText) { newValue in
|
||||||
|
homeRecentDocumentsItems = Int(newValue) ?? 3
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.multilineTextAlignment(.trailing)
|
||||||
|
|
||||||
if !accounts.isEmpty {
|
if !accounts.isEmpty {
|
||||||
Toggle("Show Favorites", isOn: $showFavoritesInHome)
|
Toggle("Show Favorites", isOn: $showFavoritesInHome)
|
||||||
|
|
||||||
|
@ -77,6 +77,8 @@
|
|||||||
3705B182267B4E4900704544 /* TrendingCategory.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3705B181267B4E4900704544 /* TrendingCategory.swift */; };
|
3705B182267B4E4900704544 /* TrendingCategory.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3705B181267B4E4900704544 /* TrendingCategory.swift */; };
|
||||||
3705B183267B4E4900704544 /* TrendingCategory.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3705B181267B4E4900704544 /* TrendingCategory.swift */; };
|
3705B183267B4E4900704544 /* TrendingCategory.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3705B181267B4E4900704544 /* TrendingCategory.swift */; };
|
||||||
3705B184267B4E4900704544 /* TrendingCategory.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3705B181267B4E4900704544 /* TrendingCategory.swift */; };
|
3705B184267B4E4900704544 /* TrendingCategory.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3705B181267B4E4900704544 /* TrendingCategory.swift */; };
|
||||||
|
3709528829283A21001ECA40 /* RecentDocumentsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3709528729283A21001ECA40 /* RecentDocumentsView.swift */; };
|
||||||
|
3709528A29283E14001ECA40 /* NoDocumentsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3709528929283E14001ECA40 /* NoDocumentsView.swift */; };
|
||||||
37095E82291DC85400301883 /* ShareViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37095E81291DC85400301883 /* ShareViewController.swift */; };
|
37095E82291DC85400301883 /* ShareViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37095E81291DC85400301883 /* ShareViewController.swift */; };
|
||||||
37095E89291DC85400301883 /* Open in Yattee.appex in Embed Foundation Extensions */ = {isa = PBXBuildFile; fileRef = 37095E7F291DC85400301883 /* Open in Yattee.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; };
|
37095E89291DC85400301883 /* Open in Yattee.appex in Embed Foundation Extensions */ = {isa = PBXBuildFile; fileRef = 37095E7F291DC85400301883 /* Open in Yattee.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; };
|
||||||
37095E8D291DD5DA00301883 /* URLBookmarkModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37F5E8B5291BE9D0006C15F5 /* URLBookmarkModel.swift */; };
|
37095E8D291DD5DA00301883 /* URLBookmarkModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37F5E8B5291BE9D0006C15F5 /* URLBookmarkModel.swift */; };
|
||||||
@ -1020,6 +1022,8 @@
|
|||||||
3703100127B0713600ECDDAA /* PlayerGestures.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PlayerGestures.swift; sourceTree = "<group>"; };
|
3703100127B0713600ECDDAA /* PlayerGestures.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PlayerGestures.swift; sourceTree = "<group>"; };
|
||||||
3705B17F267B4DFB00704544 /* TrendingCountry.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TrendingCountry.swift; sourceTree = "<group>"; };
|
3705B17F267B4DFB00704544 /* TrendingCountry.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TrendingCountry.swift; sourceTree = "<group>"; };
|
||||||
3705B181267B4E4900704544 /* TrendingCategory.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TrendingCategory.swift; sourceTree = "<group>"; };
|
3705B181267B4E4900704544 /* TrendingCategory.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TrendingCategory.swift; sourceTree = "<group>"; };
|
||||||
|
3709528729283A21001ECA40 /* RecentDocumentsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RecentDocumentsView.swift; sourceTree = "<group>"; };
|
||||||
|
3709528929283E14001ECA40 /* NoDocumentsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NoDocumentsView.swift; sourceTree = "<group>"; };
|
||||||
37095E7F291DC85400301883 /* Open in Yattee.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = "Open in Yattee.appex"; sourceTree = BUILT_PRODUCTS_DIR; };
|
37095E7F291DC85400301883 /* Open in Yattee.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = "Open in Yattee.appex"; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||||
37095E81291DC85400301883 /* ShareViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ShareViewController.swift; sourceTree = "<group>"; };
|
37095E81291DC85400301883 /* ShareViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ShareViewController.swift; sourceTree = "<group>"; };
|
||||||
37095E86291DC85400301883 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
37095E86291DC85400301883 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||||
@ -1873,6 +1877,8 @@
|
|||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
37494EA429200B14000DF176 /* DocumentsView.swift */,
|
37494EA429200B14000DF176 /* DocumentsView.swift */,
|
||||||
|
3709528929283E14001ECA40 /* NoDocumentsView.swift */,
|
||||||
|
3709528729283A21001ECA40 /* RecentDocumentsView.swift */,
|
||||||
);
|
);
|
||||||
path = Documents;
|
path = Documents;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
@ -2873,6 +2879,7 @@
|
|||||||
375EC959289EEB8200751258 /* QualityProfileForm.swift in Sources */,
|
375EC959289EEB8200751258 /* QualityProfileForm.swift in Sources */,
|
||||||
37D2E0D028B67DBC00F64D52 /* AnimationCompletionObserverModifier.swift in Sources */,
|
37D2E0D028B67DBC00F64D52 /* AnimationCompletionObserverModifier.swift in Sources */,
|
||||||
3727B74A27872A920021C15E /* VisualEffectBlur-iOS.swift in Sources */,
|
3727B74A27872A920021C15E /* VisualEffectBlur-iOS.swift in Sources */,
|
||||||
|
3709528829283A21001ECA40 /* RecentDocumentsView.swift in Sources */,
|
||||||
37977583268922F600DD52A8 /* InvidiousAPI.swift in Sources */,
|
37977583268922F600DD52A8 /* InvidiousAPI.swift in Sources */,
|
||||||
374AB3D728BCAF0000DF56FB /* SeekModel.swift in Sources */,
|
374AB3D728BCAF0000DF56FB /* SeekModel.swift in Sources */,
|
||||||
37130A5F277657300033018A /* PersistenceController.swift in Sources */,
|
37130A5F277657300033018A /* PersistenceController.swift in Sources */,
|
||||||
@ -2916,6 +2923,7 @@
|
|||||||
37CC3F4C270CFE1700608308 /* PlayerQueueView.swift in Sources */,
|
37CC3F4C270CFE1700608308 /* PlayerQueueView.swift in Sources */,
|
||||||
37FFC440272734C3009FFD26 /* Throttle.swift in Sources */,
|
37FFC440272734C3009FFD26 /* Throttle.swift in Sources */,
|
||||||
37DD9DB42785D58D00539416 /* RefreshControlModifier.swift in Sources */,
|
37DD9DB42785D58D00539416 /* RefreshControlModifier.swift in Sources */,
|
||||||
|
3709528A29283E14001ECA40 /* NoDocumentsView.swift in Sources */,
|
||||||
3705B182267B4E4900704544 /* TrendingCategory.swift in Sources */,
|
3705B182267B4E4900704544 /* TrendingCategory.swift in Sources */,
|
||||||
378AE940274EDFB5006A4EE1 /* Tint+Backport.swift in Sources */,
|
378AE940274EDFB5006A4EE1 /* Tint+Backport.swift in Sources */,
|
||||||
376BE50927347B5F009AD608 /* SettingsHeader.swift in Sources */,
|
376BE50927347B5F009AD608 /* SettingsHeader.swift in Sources */,
|
||||||
|
Loading…
Reference in New Issue
Block a user