Merge branch 'main' into multi-server-url
This commit is contained in:
commit
1ee02dfcb0
|
@ -96,3 +96,4 @@ iOSInjectionProject/
|
|||
.Trashes
|
||||
ehthumbs.db
|
||||
Thumbs.db
|
||||
Shared/Generated/Strings.swift
|
||||
|
|
|
@ -20,7 +20,7 @@ struct MediaPlayButtonRowView: View {
|
|||
NavigationLink(destination: VideoPlayerView(item: viewModel.item).ignoresSafeArea()) {
|
||||
MediaViewActionButton(icon: "play.fill", scrollView: $wrappedScrollView)
|
||||
}
|
||||
Text(viewModel.item.getItemProgressString() != "" ? "\(viewModel.item.getItemProgressString()) left" : "Play")
|
||||
Text(viewModel.item.getItemProgressString() != "" ? "\(viewModel.item.getItemProgressString()) left" : L10n.play)
|
||||
.font(.caption)
|
||||
}
|
||||
VStack {
|
||||
|
|
|
@ -68,7 +68,7 @@ struct PortraitItemElement: View {
|
|||
.font(.caption)
|
||||
.fontWeight(.medium)
|
||||
} else {
|
||||
Text("S\(String(item.parentIndexNumber ?? 0)):E\(String(item.indexNumber ?? 0))")
|
||||
Text(L10n.seasonAndEpisode(String(item.parentIndexNumber ?? 0), String(item.indexNumber ?? 0)))
|
||||
.foregroundColor(.secondary)
|
||||
.font(.caption)
|
||||
.fontWeight(.medium)
|
||||
|
|
|
@ -22,7 +22,7 @@ struct BasicAppSettingsView: View {
|
|||
var body: some View {
|
||||
Form {
|
||||
Section {
|
||||
Picker(NSLocalizedString("Appearance", comment: ""), selection: $appAppearance) {
|
||||
Picker(L10n.appearance, selection: $appAppearance) {
|
||||
ForEach(self.viewModel.appearances, id: \.self) { appearance in
|
||||
Text(appearance.localizedName).tag(appearance.rawValue)
|
||||
}
|
||||
|
@ -30,21 +30,21 @@ struct BasicAppSettingsView: View {
|
|||
UIApplication.shared.windows.first?.overrideUserInterfaceStyle = appAppearance.style
|
||||
})
|
||||
} header: {
|
||||
Text("Accessibility")
|
||||
L10n.accessibility.text
|
||||
}
|
||||
|
||||
Button {
|
||||
resetTapped = true
|
||||
} label: {
|
||||
Text("Reset")
|
||||
L10n.reset.text
|
||||
}
|
||||
}
|
||||
.alert("Reset", isPresented: $resetTapped, actions: {
|
||||
.alert(L10n.reset, isPresented: $resetTapped, actions: {
|
||||
Button(role: .destructive) {
|
||||
viewModel.reset()
|
||||
basicAppSettingsRouter.dismissCoordinator()
|
||||
} label: {
|
||||
Text("Reset")
|
||||
L10n.reset.text
|
||||
}
|
||||
})
|
||||
.navigationTitle("Settings")
|
||||
|
|
|
@ -17,7 +17,7 @@ struct ConnectToServerView: View {
|
|||
var body: some View {
|
||||
List {
|
||||
Section {
|
||||
TextField(NSLocalizedString("Server URL", comment: ""), text: $uri)
|
||||
TextField(L10n.serverURL, text: $uri)
|
||||
.disableAutocorrection(true)
|
||||
.autocapitalization(.none)
|
||||
.keyboardType(.URL)
|
||||
|
@ -25,7 +25,7 @@ struct ConnectToServerView: View {
|
|||
viewModel.connectToServer(uri: uri)
|
||||
} label: {
|
||||
HStack {
|
||||
Text("Connect")
|
||||
L10n.connect.text
|
||||
Spacer()
|
||||
if viewModel.isLoading {
|
||||
ProgressView()
|
||||
|
@ -37,7 +37,7 @@ struct ConnectToServerView: View {
|
|||
Text("Connect to a Jellyfin server")
|
||||
}
|
||||
|
||||
Section(header: Text("Local Servers")) {
|
||||
Section(header: L10n.localServers.text) {
|
||||
if viewModel.searching {
|
||||
ProgressView()
|
||||
}
|
||||
|
@ -68,6 +68,6 @@ struct ConnectToServerView: View {
|
|||
message: Text(viewModel.errorMessage?.displayMessage ?? "Unknown Error"),
|
||||
dismissButton: .cancel())
|
||||
}
|
||||
.navigationTitle("Connect")
|
||||
.navigationTitle(L10n.connect)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -20,7 +20,7 @@ struct ContinueWatchingView: View {
|
|||
var body: some View {
|
||||
VStack(alignment: .leading) {
|
||||
if items.count > 0 {
|
||||
Text("Continue Watching")
|
||||
L10n.continueWatching.text
|
||||
.font(.headline)
|
||||
.fontWeight(.semibold)
|
||||
.padding(.leading, 90)
|
||||
|
|
|
@ -38,7 +38,7 @@ struct HomeView: View {
|
|||
self.homeRouter.route(to: \.modalLibrary, (.init(parentID: libraryID, filters: viewModel.recentFilterSet), title: library?.name ?? ""))
|
||||
} label: {
|
||||
HStack {
|
||||
Text("Latest \(library?.name ?? "")")
|
||||
Text(L10n.latestWithString(library?.name ?? ""))
|
||||
.font(.headline)
|
||||
.fontWeight(.semibold)
|
||||
Image(systemName: "chevron.forward.circle.fill")
|
||||
|
|
|
@ -76,7 +76,7 @@ struct EpisodeItemView: View {
|
|||
HStack(alignment: .top) {
|
||||
VStack(alignment: .trailing) {
|
||||
if studio != nil {
|
||||
Text("STUDIO")
|
||||
L10n.studio.text
|
||||
.font(.body)
|
||||
.fontWeight(.semibold)
|
||||
.foregroundColor(.primary)
|
||||
|
@ -88,7 +88,7 @@ struct EpisodeItemView: View {
|
|||
}
|
||||
|
||||
if director != nil {
|
||||
Text("DIRECTOR")
|
||||
L10n.director.text
|
||||
.font(.body)
|
||||
.fontWeight(.semibold)
|
||||
.foregroundColor(.primary)
|
||||
|
@ -100,7 +100,7 @@ struct EpisodeItemView: View {
|
|||
}
|
||||
|
||||
if !actors.isEmpty {
|
||||
Text("CAST")
|
||||
L10n.cast.text
|
||||
.font(.body)
|
||||
.fontWeight(.semibold)
|
||||
.foregroundColor(.primary)
|
||||
|
@ -133,7 +133,7 @@ struct EpisodeItemView: View {
|
|||
NavigationLink(destination: VideoPlayerView(item: viewModel.item).ignoresSafeArea()) {
|
||||
MediaViewActionButton(icon: "play.fill")
|
||||
}
|
||||
Text(viewModel.item.getItemProgressString() != "" ? "\(viewModel.item.getItemProgressString()) left" : "Play")
|
||||
Text(viewModel.item.getItemProgressString() != "" ? "\(viewModel.item.getItemProgressString()) left" : L10n.play)
|
||||
.font(.caption)
|
||||
}
|
||||
VStack {
|
||||
|
@ -152,7 +152,7 @@ struct EpisodeItemView: View {
|
|||
}.padding(.top, 50)
|
||||
|
||||
if !viewModel.similarItems.isEmpty {
|
||||
Text("More Like This")
|
||||
L10n.moreLikeThis.text
|
||||
.font(.headline)
|
||||
.fontWeight(.semibold)
|
||||
ScrollView(.horizontal) {
|
||||
|
|
|
@ -40,7 +40,7 @@ struct ItemView: View {
|
|||
} else if item.type == "Episode" {
|
||||
EpisodeItemView(viewModel: .init(item: item))
|
||||
} else {
|
||||
Text("Type: \(item.type ?? "") not implemented yet :(")
|
||||
Text(L10n.notImplementedYetWithType(item.type ?? ""))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -77,7 +77,7 @@ struct MovieItemView: View {
|
|||
HStack {
|
||||
VStack(alignment: .trailing) {
|
||||
if studio != nil {
|
||||
Text("STUDIO")
|
||||
L10n.studio.text
|
||||
.font(.body)
|
||||
.fontWeight(.semibold)
|
||||
.foregroundColor(.primary)
|
||||
|
@ -89,7 +89,7 @@ struct MovieItemView: View {
|
|||
}
|
||||
|
||||
if director != nil {
|
||||
Text("DIRECTOR")
|
||||
L10n.director.text
|
||||
.font(.body)
|
||||
.fontWeight(.semibold)
|
||||
.foregroundColor(.primary)
|
||||
|
@ -101,7 +101,7 @@ struct MovieItemView: View {
|
|||
}
|
||||
|
||||
if !actors.isEmpty {
|
||||
Text("CAST")
|
||||
L10n.cast.text
|
||||
.font(.body)
|
||||
.fontWeight(.semibold)
|
||||
.foregroundColor(.primary)
|
||||
|
@ -133,7 +133,7 @@ struct MovieItemView: View {
|
|||
}.padding(.top, 50)
|
||||
|
||||
if !viewModel.similarItems.isEmpty {
|
||||
Text("More Like This")
|
||||
L10n.moreLikeThis.text
|
||||
.font(.headline)
|
||||
.fontWeight(.semibold)
|
||||
ScrollView(.horizontal) {
|
||||
|
|
|
@ -95,7 +95,7 @@ struct SeasonItemView: View {
|
|||
}.padding(.top, 50)
|
||||
|
||||
if !viewModel.episodes.isEmpty {
|
||||
Text("Episodes")
|
||||
L10n.episodes.text
|
||||
.font(.headline)
|
||||
.fontWeight(.semibold)
|
||||
ScrollView(.horizontal) {
|
||||
|
|
|
@ -79,7 +79,7 @@ struct SeriesItemView: View {
|
|||
HStack {
|
||||
VStack(alignment: .trailing) {
|
||||
if studio != nil {
|
||||
Text("STUDIO")
|
||||
L10n.studio.text
|
||||
.font(.body)
|
||||
.fontWeight(.semibold)
|
||||
.foregroundColor(.primary)
|
||||
|
@ -91,7 +91,7 @@ struct SeriesItemView: View {
|
|||
}
|
||||
|
||||
if director != nil {
|
||||
Text("DIRECTOR")
|
||||
L10n.director.text
|
||||
.font(.body)
|
||||
.fontWeight(.semibold)
|
||||
.foregroundColor(.primary)
|
||||
|
@ -103,7 +103,7 @@ struct SeriesItemView: View {
|
|||
}
|
||||
|
||||
if !actors.isEmpty {
|
||||
Text("CAST")
|
||||
L10n.cast.text
|
||||
.font(.body)
|
||||
.fontWeight(.semibold)
|
||||
.foregroundColor(.primary)
|
||||
|
@ -135,7 +135,7 @@ struct SeriesItemView: View {
|
|||
}
|
||||
}.padding(.top, 50)
|
||||
if !viewModel.seasons.isEmpty {
|
||||
Text("Seasons")
|
||||
L10n.seasons.text
|
||||
.font(.headline)
|
||||
.fontWeight(.semibold)
|
||||
ScrollView(.horizontal) {
|
||||
|
@ -153,7 +153,7 @@ struct SeriesItemView: View {
|
|||
}
|
||||
|
||||
if !viewModel.similarItems.isEmpty {
|
||||
Text("More Like This")
|
||||
L10n.moreLikeThis.text
|
||||
.font(.headline)
|
||||
.fontWeight(.semibold)
|
||||
ScrollView(.horizontal) {
|
||||
|
|
|
@ -31,32 +31,32 @@ struct LibraryFilterView: View {
|
|||
} else {
|
||||
Form {
|
||||
if viewModel.enabledFilterType.contains(.genre) {
|
||||
MultiSelector(label: NSLocalizedString("Genres", comment: ""),
|
||||
MultiSelector(label: L10n.genres,
|
||||
options: viewModel.possibleGenres,
|
||||
optionToString: { $0.name ?? "" },
|
||||
selected: $viewModel.modifiedFilters.withGenres)
|
||||
}
|
||||
if viewModel.enabledFilterType.contains(.filter) {
|
||||
MultiSelector(label: NSLocalizedString("Filters", comment: ""),
|
||||
MultiSelector(label: L10n.filters,
|
||||
options: viewModel.possibleItemFilters,
|
||||
optionToString: { $0.localized },
|
||||
selected: $viewModel.modifiedFilters.filters)
|
||||
}
|
||||
if viewModel.enabledFilterType.contains(.tag) {
|
||||
MultiSelector(label: NSLocalizedString("Tags", comment: ""),
|
||||
MultiSelector(label: L10n.tags,
|
||||
options: viewModel.possibleTags,
|
||||
optionToString: { $0 },
|
||||
selected: $viewModel.modifiedFilters.tags)
|
||||
}
|
||||
if viewModel.enabledFilterType.contains(.sortBy) {
|
||||
Picker(selection: $viewModel.selectedSortBy, label: Text("Sort by")) {
|
||||
Picker(selection: $viewModel.selectedSortBy, label: L10n.sortBy.text) {
|
||||
ForEach(viewModel.possibleSortBys, id: \.self) { so in
|
||||
Text(so.localized).tag(so)
|
||||
}
|
||||
}
|
||||
}
|
||||
if viewModel.enabledFilterType.contains(.sortOrder) {
|
||||
Picker(selection: $viewModel.selectedSortOrder, label: Text("Display order")) {
|
||||
Picker(selection: $viewModel.selectedSortOrder, label: L10n.displayOrder.text) {
|
||||
ForEach(viewModel.possibleSortOrders, id: \.self) { so in
|
||||
Text(so.rawValue).tag(so)
|
||||
}
|
||||
|
@ -68,7 +68,7 @@ struct LibraryFilterView: View {
|
|||
self.filters = viewModel.modifiedFilters
|
||||
filterRouter.dismissCoordinator()
|
||||
} label: {
|
||||
Text("Reset")
|
||||
L10n.reset.text
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -86,7 +86,7 @@ struct LibraryFilterView: View {
|
|||
self.filters = viewModel.modifiedFilters
|
||||
filterRouter.dismissCoordinator()
|
||||
} label: {
|
||||
Text("Apply")
|
||||
L10n.apply.text
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -44,7 +44,7 @@ struct LibrarySearchView: View {
|
|||
var suggestionsListView: some View {
|
||||
ScrollView {
|
||||
LazyVStack(spacing: 8) {
|
||||
Text("Suggestions")
|
||||
L10n.suggestions.text
|
||||
.font(.headline)
|
||||
.fontWeight(.bold)
|
||||
.foregroundColor(.primary)
|
||||
|
|
|
@ -88,7 +88,7 @@ struct LibraryView: View {
|
|||
.ignoresSafeArea(.all)
|
||||
} else {
|
||||
VStack {
|
||||
Text("No results.")
|
||||
L10n.noResults.text
|
||||
Button { } label: {
|
||||
Text("Reload")
|
||||
}
|
||||
|
|
|
@ -77,7 +77,7 @@ struct MovieLibrariesView: View {
|
|||
.ignoresSafeArea(.all)
|
||||
} else {
|
||||
VStack {
|
||||
Text("No results.")
|
||||
L10n.noResults.text
|
||||
Button {
|
||||
print("movieLibraries reload")
|
||||
} label: {
|
||||
|
|
|
@ -19,7 +19,7 @@ struct NextUpView: View {
|
|||
var body: some View {
|
||||
VStack(alignment: .leading) {
|
||||
if items.count > 0 {
|
||||
Text("Next Up")
|
||||
L10n.nextUp.text
|
||||
.font(.headline)
|
||||
.fontWeight(.semibold)
|
||||
.padding(.leading, 90)
|
||||
|
|
|
@ -72,7 +72,7 @@ struct ServerListView: View {
|
|||
Button {
|
||||
serverListRouter.route(to: \.connectToServer)
|
||||
} label: {
|
||||
Text("Connect")
|
||||
L10n.connect.text
|
||||
.bold()
|
||||
.font(.callout)
|
||||
}
|
||||
|
|
|
@ -22,7 +22,7 @@ struct SettingsView: View {
|
|||
|
||||
var body: some View {
|
||||
Form {
|
||||
Section(header: Text("Playback settings")) {
|
||||
Section(header: L10n.playbackSettings.text) {
|
||||
Picker("Default local quality", selection: $inNetworkStreamBitrate) {
|
||||
ForEach(self.viewModel.bitrates, id: \.self) { bitrate in
|
||||
Text(bitrate.name).tag(bitrate.value)
|
||||
|
@ -36,7 +36,7 @@ struct SettingsView: View {
|
|||
}
|
||||
}
|
||||
|
||||
Section(header: Text("Accessibility")) {
|
||||
Section(header: L10n.accessibility.text) {
|
||||
Toggle("Automatically show subtitles", isOn: $isAutoSelectSubtitles)
|
||||
SearchablePicker(label: "Preferred subtitle language",
|
||||
options: viewModel.langs,
|
||||
|
@ -58,12 +58,12 @@ struct SettingsView: View {
|
|||
|
||||
Section(header: Text(SessionManager.main.currentLogin.server.name)) {
|
||||
HStack {
|
||||
Text("Signed in as \(SessionManager.main.currentLogin.user.username)").foregroundColor(.primary)
|
||||
Text(L10n.signedInAsWithString(SessionManager.main.currentLogin.user.username)).foregroundColor(.primary)
|
||||
Spacer()
|
||||
Button {
|
||||
SwiftfinNotificationCenter.main.post(name: SwiftfinNotificationCenter.Keys.didSignOut, object: nil)
|
||||
} label: {
|
||||
Text("Switch user").font(.callout)
|
||||
L10n.switchUser.text.font(.callout)
|
||||
}
|
||||
}
|
||||
Button {
|
||||
|
|
|
@ -77,7 +77,7 @@ struct TVLibrariesView: View {
|
|||
.ignoresSafeArea(.all)
|
||||
} else {
|
||||
VStack {
|
||||
Text("No results.")
|
||||
L10n.noResults.text
|
||||
Button {
|
||||
print("tvLibraries reload")
|
||||
} label: {
|
||||
|
|
|
@ -20,11 +20,11 @@ struct UserSignInView: View {
|
|||
Form {
|
||||
|
||||
Section {
|
||||
TextField("Username", text: $username)
|
||||
TextField(L10n.username, text: $username)
|
||||
.disableAutocorrection(true)
|
||||
.autocapitalization(.none)
|
||||
|
||||
SecureField("Password", text: $password)
|
||||
SecureField(L10n.password, text: $password)
|
||||
.disableAutocorrection(true)
|
||||
.autocapitalization(.none)
|
||||
|
||||
|
@ -32,7 +32,7 @@ struct UserSignInView: View {
|
|||
viewModel.login(username: username, password: password)
|
||||
} label: {
|
||||
HStack {
|
||||
Text("Connect")
|
||||
L10n.connect.text
|
||||
Spacer()
|
||||
if viewModel.isLoading {
|
||||
ProgressView()
|
||||
|
|
|
@ -14,7 +14,7 @@ class AudioViewController: InfoTabViewController {
|
|||
override func viewDidLoad() {
|
||||
super.viewDidLoad()
|
||||
|
||||
tabBarItem.title = NSLocalizedString("Audio", comment: "")
|
||||
tabBarItem.title = "Audio"
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -16,7 +16,7 @@ class MediaInfoViewController: InfoTabViewController {
|
|||
override func viewDidLoad() {
|
||||
super.viewDidLoad()
|
||||
|
||||
tabBarItem.title = NSLocalizedString("Info", comment: "")
|
||||
tabBarItem.title = "Info"
|
||||
}
|
||||
|
||||
func setMedia(item: BaseItemDto) {
|
||||
|
|
|
@ -14,7 +14,7 @@ class SubtitlesViewController: InfoTabViewController {
|
|||
override func viewDidLoad() {
|
||||
super.viewDidLoad()
|
||||
|
||||
tabBarItem.title = NSLocalizedString("Subtitles", comment: "")
|
||||
tabBarItem.title = "Subtitles"
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
09389CC726819B4600AE350E /* VideoPlayerModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 09389CC626819B4500AE350E /* VideoPlayerModel.swift */; };
|
||||
09389CC826819B4600AE350E /* VideoPlayerModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 09389CC626819B4500AE350E /* VideoPlayerModel.swift */; };
|
||||
0959A5FD2686D29800C7C9A9 /* VideoUpNextView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0959A5FC2686D29800C7C9A9 /* VideoUpNextView.swift */; };
|
||||
363CADF08820D3B2055CF1D8 /* Pods_JellyfinPlayer_tvOS.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4BE2D324B040DCA2629C110D /* Pods_JellyfinPlayer_tvOS.framework */; };
|
||||
531069572684E7EE00CFFDBA /* InfoTabBarViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 531069502684E7EE00CFFDBA /* InfoTabBarViewController.swift */; };
|
||||
531069582684E7EE00CFFDBA /* MediaInfoView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 531069512684E7EE00CFFDBA /* MediaInfoView.swift */; };
|
||||
531069592684E7EE00CFFDBA /* SubtitlesView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 531069522684E7EE00CFFDBA /* SubtitlesView.swift */; };
|
||||
|
@ -148,12 +149,11 @@
|
|||
53DE4BD2267098F300739748 /* SearchBarView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 53DE4BD1267098F300739748 /* SearchBarView.swift */; };
|
||||
53DF641E263D9C0600A7CD1A /* LibraryView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 53DF641D263D9C0600A7CD1A /* LibraryView.swift */; };
|
||||
53E4E649263F725B00F67C6B /* MultiSelectorView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 53E4E648263F725B00F67C6B /* MultiSelectorView.swift */; };
|
||||
53EC6E1E267E80AC006DD26A /* Pods_JellyfinPlayer_tvOS.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = EBFE1F64394BCC2EFFF1610D /* Pods_JellyfinPlayer_tvOS.framework */; };
|
||||
53EC6E21267E80B1006DD26A /* Pods_JellyfinPlayer_iOS.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3F905C1D3D3A0C9E13E7A0BC /* Pods_JellyfinPlayer_iOS.framework */; };
|
||||
53EE24E6265060780068F029 /* LibrarySearchView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 53EE24E5265060780068F029 /* LibrarySearchView.swift */; };
|
||||
53F8377D265FF67C00F456B3 /* VideoPlayerSettingsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 53F8377C265FF67C00F456B3 /* VideoPlayerSettingsView.swift */; };
|
||||
53F866442687A45F00DCD1D7 /* PortraitItemView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 53F866432687A45F00DCD1D7 /* PortraitItemView.swift */; };
|
||||
53FF7F2A263CF3F500585C35 /* LatestMediaView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 53FF7F29263CF3F500585C35 /* LatestMediaView.swift */; };
|
||||
560CA59B3956A4CA13EDAC05 /* Pods_JellyfinPlayer_iOS.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 86BAC42C3764D232C8DF8F5E /* Pods_JellyfinPlayer_iOS.framework */; };
|
||||
62133890265F83A900A81A2A /* LibraryListView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6213388F265F83A900A81A2A /* LibraryListView.swift */; };
|
||||
621338932660107500A81A2A /* StringExtensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 621338922660107500A81A2A /* StringExtensions.swift */; };
|
||||
621338B32660A07800A81A2A /* LazyView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 621338B22660A07800A81A2A /* LazyView.swift */; };
|
||||
|
@ -175,6 +175,10 @@
|
|||
625CB5752678C33500530A6E /* LibraryListViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 625CB5742678C33500530A6E /* LibraryListViewModel.swift */; };
|
||||
625CB5772678C34300530A6E /* ConnectToServerViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 625CB5762678C34300530A6E /* ConnectToServerViewModel.swift */; };
|
||||
625CB57A2678C4A400530A6E /* ActivityIndicator in Frameworks */ = {isa = PBXBuildFile; productRef = 625CB5792678C4A400530A6E /* ActivityIndicator */; };
|
||||
6264E88A27384A6F0081A12A /* NetworkError.swift in Sources */ = {isa = PBXBuildFile; fileRef = E1FCD08726C35A0D007C8DCF /* NetworkError.swift */; };
|
||||
6264E88C273850380081A12A /* Strings.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6264E88B273850380081A12A /* Strings.swift */; };
|
||||
6264E88D273850380081A12A /* Strings.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6264E88B273850380081A12A /* Strings.swift */; };
|
||||
6264E88E273850380081A12A /* Strings.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6264E88B273850380081A12A /* Strings.swift */; };
|
||||
62671DB327159C1800199D95 /* ItemCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6220D0BF26D61C5000B8E046 /* ItemCoordinator.swift */; };
|
||||
6267B3D626710B8900A7371D /* CollectionExtensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6267B3D526710B8900A7371D /* CollectionExtensions.swift */; };
|
||||
6267B3D726710B9700A7371D /* CollectionExtensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6267B3D526710B8900A7371D /* CollectionExtensions.swift */; };
|
||||
|
@ -354,17 +358,17 @@
|
|||
E1FCD08926C35A0D007C8DCF /* NetworkError.swift in Sources */ = {isa = PBXBuildFile; fileRef = E1FCD08726C35A0D007C8DCF /* NetworkError.swift */; };
|
||||
E1FCD09626C47118007C8DCF /* ErrorMessage.swift in Sources */ = {isa = PBXBuildFile; fileRef = E1FCD09526C47118007C8DCF /* ErrorMessage.swift */; };
|
||||
E1FCD09726C47118007C8DCF /* ErrorMessage.swift in Sources */ = {isa = PBXBuildFile; fileRef = E1FCD09526C47118007C8DCF /* ErrorMessage.swift */; };
|
||||
E1FCD09926C4F358007C8DCF /* NetworkError.swift in Sources */ = {isa = PBXBuildFile; fileRef = E1FCD08726C35A0D007C8DCF /* NetworkError.swift */; };
|
||||
E1FCD09A26C4F35A007C8DCF /* ErrorMessage.swift in Sources */ = {isa = PBXBuildFile; fileRef = E1FCD09526C47118007C8DCF /* ErrorMessage.swift */; };
|
||||
EABFD69FA6D5DBB248A494AA /* Pods_WidgetExtension.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 59AFF849629F3C787909A911 /* Pods_WidgetExtension.framework */; };
|
||||
/* End PBXBuildFile section */
|
||||
|
||||
/* Begin PBXContainerItemProxy section */
|
||||
628B952B2670CABE0091AF3B /* PBXContainerItemProxy */ = {
|
||||
6264E888273848760081A12A /* PBXContainerItemProxy */ = {
|
||||
isa = PBXContainerItemProxy;
|
||||
containerPortal = 5377CBE9263B596A003A4E83 /* Project object */;
|
||||
proxyType = 1;
|
||||
remoteGlobalIDString = 628B951F2670CABD0091AF3B;
|
||||
remoteInfo = WidgetExtensionExtension;
|
||||
remoteInfo = WidgetExtension;
|
||||
};
|
||||
/* End PBXContainerItemProxy section */
|
||||
|
||||
|
@ -396,8 +400,10 @@
|
|||
091B5A882683142E00D78B61 /* UDPBroadCastConnection.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UDPBroadCastConnection.swift; sourceTree = "<group>"; };
|
||||
09389CC626819B4500AE350E /* VideoPlayerModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VideoPlayerModel.swift; sourceTree = "<group>"; };
|
||||
0959A5FC2686D29800C7C9A9 /* VideoUpNextView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VideoUpNextView.swift; sourceTree = "<group>"; };
|
||||
3773C07648173CE7FEC083D5 /* Pods-JellyfinPlayer iOS.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-JellyfinPlayer iOS.debug.xcconfig"; path = "Target Support Files/Pods-JellyfinPlayer iOS/Pods-JellyfinPlayer iOS.debug.xcconfig"; sourceTree = "<group>"; };
|
||||
3F905C1D3D3A0C9E13E7A0BC /* Pods_JellyfinPlayer_iOS.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_JellyfinPlayer_iOS.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
14E199C7BBA98782CAD2F0D4 /* Pods-JellyfinPlayer iOS.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-JellyfinPlayer iOS.release.xcconfig"; path = "Target Support Files/Pods-JellyfinPlayer iOS/Pods-JellyfinPlayer iOS.release.xcconfig"; sourceTree = "<group>"; };
|
||||
20CA36DDD247EED8D16438A5 /* Pods-JellyfinPlayer tvOS.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-JellyfinPlayer tvOS.release.xcconfig"; path = "Target Support Files/Pods-JellyfinPlayer tvOS/Pods-JellyfinPlayer tvOS.release.xcconfig"; sourceTree = "<group>"; };
|
||||
4BDCEE3B49CF70A9E9BA3CD8 /* Pods-WidgetExtension.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-WidgetExtension.debug.xcconfig"; path = "Target Support Files/Pods-WidgetExtension/Pods-WidgetExtension.debug.xcconfig"; sourceTree = "<group>"; };
|
||||
4BE2D324B040DCA2629C110D /* Pods_JellyfinPlayer_tvOS.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_JellyfinPlayer_tvOS.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
531069502684E7EE00CFFDBA /* InfoTabBarViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = InfoTabBarViewController.swift; sourceTree = "<group>"; };
|
||||
531069512684E7EE00CFFDBA /* MediaInfoView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MediaInfoView.swift; sourceTree = "<group>"; };
|
||||
531069522684E7EE00CFFDBA /* SubtitlesView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SubtitlesView.swift; sourceTree = "<group>"; };
|
||||
|
@ -495,6 +501,7 @@
|
|||
53F8377C265FF67C00F456B3 /* VideoPlayerSettingsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VideoPlayerSettingsView.swift; sourceTree = "<group>"; };
|
||||
53F866432687A45F00DCD1D7 /* PortraitItemView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PortraitItemView.swift; sourceTree = "<group>"; };
|
||||
53FF7F29263CF3F500585C35 /* LatestMediaView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LatestMediaView.swift; sourceTree = "<group>"; };
|
||||
59AFF849629F3C787909A911 /* Pods_WidgetExtension.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_WidgetExtension.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
6213388F265F83A900A81A2A /* LibraryListView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LibraryListView.swift; sourceTree = "<group>"; };
|
||||
621338922660107500A81A2A /* StringExtensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StringExtensions.swift; sourceTree = "<group>"; };
|
||||
621338B22660A07800A81A2A /* LazyView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LazyView.swift; sourceTree = "<group>"; };
|
||||
|
@ -514,6 +521,7 @@
|
|||
625CB5762678C34300530A6E /* ConnectToServerViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ConnectToServerViewModel.swift; sourceTree = "<group>"; };
|
||||
625CB57B2678CE1000530A6E /* ViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewModel.swift; sourceTree = "<group>"; };
|
||||
625CB57D2678E81E00530A6E /* TVVLCKit.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; name = TVVLCKit.xcframework; path = Carthage/Build/TVVLCKit.xcframework; sourceTree = "<group>"; };
|
||||
6264E88B273850380081A12A /* Strings.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Strings.swift; sourceTree = "<group>"; };
|
||||
6267B3D526710B8900A7371D /* CollectionExtensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CollectionExtensions.swift; sourceTree = "<group>"; };
|
||||
6267B3D92671138200A7371D /* ImageExtensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ImageExtensions.swift; sourceTree = "<group>"; };
|
||||
628B95202670CABD0091AF3B /* WidgetExtension.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = WidgetExtension.appex; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
|
@ -540,8 +548,10 @@
|
|||
62EC352E267666A5000E9F2D /* SessionManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SessionManager.swift; sourceTree = "<group>"; };
|
||||
62EC353326766B03000E9F2D /* DeviceRotationViewModifier.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DeviceRotationViewModifier.swift; sourceTree = "<group>"; };
|
||||
62ECA01726FA685A00E8EBB7 /* DeepLink.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DeepLink.swift; sourceTree = "<group>"; };
|
||||
772F6DAB8534FD1DB45B7687 /* Pods-JellyfinPlayer iOS.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-JellyfinPlayer iOS.debug.xcconfig"; path = "Target Support Files/Pods-JellyfinPlayer iOS/Pods-JellyfinPlayer iOS.debug.xcconfig"; sourceTree = "<group>"; };
|
||||
86BAC42C3764D232C8DF8F5E /* Pods_JellyfinPlayer_iOS.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_JellyfinPlayer_iOS.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
AE8C3158265D6F90008AA076 /* bitrates.json */ = {isa = PBXFileReference; lastKnownFileType = text.json; path = bitrates.json; sourceTree = "<group>"; };
|
||||
BEEC50E7EFD4848C0E320941 /* Pods-JellyfinPlayer iOS.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-JellyfinPlayer iOS.release.xcconfig"; path = "Target Support Files/Pods-JellyfinPlayer iOS/Pods-JellyfinPlayer iOS.release.xcconfig"; sourceTree = "<group>"; };
|
||||
B598C62749E5EFD37280FCC3 /* Pods-JellyfinPlayer tvOS.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-JellyfinPlayer tvOS.debug.xcconfig"; path = "Target Support Files/Pods-JellyfinPlayer tvOS/Pods-JellyfinPlayer tvOS.debug.xcconfig"; sourceTree = "<group>"; };
|
||||
C40CD921271F8CD8000FB198 /* MoviesLibrariesCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MoviesLibrariesCoordinator.swift; sourceTree = "<group>"; };
|
||||
C40CD924271F8D1E000FB198 /* MovieLibrariesViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MovieLibrariesViewModel.swift; sourceTree = "<group>"; };
|
||||
C40CD927271F8DAB000FB198 /* MovieLibrariesView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MovieLibrariesView.swift; sourceTree = "<group>"; };
|
||||
|
@ -551,8 +561,6 @@
|
|||
C4BE076D2720FEA8003F4AD1 /* PortraitItemElement.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PortraitItemElement.swift; sourceTree = "<group>"; };
|
||||
C4E508172703E8190045C9AB /* LibraryListView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LibraryListView.swift; sourceTree = "<group>"; };
|
||||
C4E5081C2703F8370045C9AB /* LibrarySearchView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LibrarySearchView.swift; sourceTree = "<group>"; };
|
||||
D79953919FED0C4DF72BA578 /* Pods-JellyfinPlayer tvOS.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-JellyfinPlayer tvOS.release.xcconfig"; path = "Target Support Files/Pods-JellyfinPlayer tvOS/Pods-JellyfinPlayer tvOS.release.xcconfig"; sourceTree = "<group>"; };
|
||||
DE5004F745B19E28744A7DE7 /* Pods-JellyfinPlayer tvOS.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-JellyfinPlayer tvOS.debug.xcconfig"; path = "Target Support Files/Pods-JellyfinPlayer tvOS/Pods-JellyfinPlayer tvOS.debug.xcconfig"; sourceTree = "<group>"; };
|
||||
E100720626BDABC100CE3E31 /* MediaPlayButtonRowView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MediaPlayButtonRowView.swift; sourceTree = "<group>"; };
|
||||
E11B1B6B2718CD68006DA3E8 /* JellyfinAPIError.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = JellyfinAPIError.swift; sourceTree = "<group>"; };
|
||||
E11D224127378428003F9CB3 /* ServerDetailCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ServerDetailCoordinator.swift; sourceTree = "<group>"; };
|
||||
|
@ -609,7 +617,7 @@
|
|||
E1F0204D26CCCA74001C1C3B /* VideoPlayerJumpLength.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VideoPlayerJumpLength.swift; sourceTree = "<group>"; };
|
||||
E1FCD08726C35A0D007C8DCF /* NetworkError.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NetworkError.swift; sourceTree = "<group>"; };
|
||||
E1FCD09526C47118007C8DCF /* ErrorMessage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ErrorMessage.swift; sourceTree = "<group>"; };
|
||||
EBFE1F64394BCC2EFFF1610D /* Pods_JellyfinPlayer_tvOS.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_JellyfinPlayer_tvOS.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
FDEDADB92FA8523BC8432E45 /* Pods-WidgetExtension.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-WidgetExtension.release.xcconfig"; path = "Target Support Files/Pods-WidgetExtension/Pods-WidgetExtension.release.xcconfig"; sourceTree = "<group>"; };
|
||||
/* End PBXFileReference section */
|
||||
|
||||
/* Begin PBXFrameworksBuildPhase section */
|
||||
|
@ -619,7 +627,6 @@
|
|||
files = (
|
||||
53649AAF269CFAF600A2D8B7 /* Puppy in Frameworks */,
|
||||
E1218C9E271A2CD600EA0737 /* CombineExt in Frameworks */,
|
||||
53EC6E1E267E80AC006DD26A /* Pods_JellyfinPlayer_tvOS.framework in Frameworks */,
|
||||
E1218CA0271A2CF200EA0737 /* Nuke in Frameworks */,
|
||||
6220D0C926D63F3700B8E046 /* Stinsen in Frameworks */,
|
||||
53A431BF266B0FFE0016769F /* JellyfinAPI in Frameworks */,
|
||||
|
@ -630,6 +637,7 @@
|
|||
E13DD3CD27164CA7009D4DAF /* CoreStore in Frameworks */,
|
||||
E12186DE2718F1C50010884C /* Defaults in Frameworks */,
|
||||
53ABFDED26799D7700886593 /* ActivityIndicator in Frameworks */,
|
||||
363CADF08820D3B2055CF1D8 /* Pods_JellyfinPlayer_tvOS.framework in Frameworks */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
|
@ -641,7 +649,6 @@
|
|||
53649AAD269CFAEA00A2D8B7 /* Puppy in Frameworks */,
|
||||
62C29E9C26D0FE4200C1D2E7 /* Stinsen in Frameworks */,
|
||||
E1A99999271A3429008E78C0 /* SwiftUICollection in Frameworks */,
|
||||
53EC6E21267E80B1006DD26A /* Pods_JellyfinPlayer_iOS.framework in Frameworks */,
|
||||
E1218C9A271A26BA00EA0737 /* Nuke in Frameworks */,
|
||||
E1B6DCEA271A23880015B715 /* SwiftyJSON in Frameworks */,
|
||||
53352571265EA0A0006CCA86 /* Introspect in Frameworks */,
|
||||
|
@ -649,6 +656,7 @@
|
|||
625CB57A2678C4A400530A6E /* ActivityIndicator in Frameworks */,
|
||||
E1B6DCE8271A23780015B715 /* CombineExt in Frameworks */,
|
||||
53A431BD266B0FF20016769F /* JellyfinAPI in Frameworks */,
|
||||
560CA59B3956A4CA13EDAC05 /* Pods_JellyfinPlayer_iOS.framework in Frameworks */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
|
@ -664,6 +672,7 @@
|
|||
E13DD3CF27164E1F009D4DAF /* CoreStore in Frameworks */,
|
||||
628B95352670CAEA0091AF3B /* JellyfinAPI in Frameworks */,
|
||||
E1218C9C271A26C400EA0737 /* Nuke in Frameworks */,
|
||||
EABFD69FA6D5DBB248A494AA /* Pods_WidgetExtension.framework in Frameworks */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
|
@ -794,6 +803,7 @@
|
|||
535870752669D60C00D05A09 /* Shared */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
6286F09F271C0AA500C40ED5 /* Generated */,
|
||||
62C29E9D26D0FE5900C1D2E7 /* Coordinators */,
|
||||
E1FCD08E26C466F3007C8DCF /* Errors */,
|
||||
621338912660106C00A81A2A /* Extensions */,
|
||||
|
@ -1029,8 +1039,9 @@
|
|||
53D5E3DC264B47EE00BADDC8 /* MobileVLCKit.xcframework */,
|
||||
628B95212670CABD0091AF3B /* WidgetKit.framework */,
|
||||
628B95232670CABD0091AF3B /* SwiftUI.framework */,
|
||||
3F905C1D3D3A0C9E13E7A0BC /* Pods_JellyfinPlayer_iOS.framework */,
|
||||
EBFE1F64394BCC2EFFF1610D /* Pods_JellyfinPlayer_tvOS.framework */,
|
||||
86BAC42C3764D232C8DF8F5E /* Pods_JellyfinPlayer_iOS.framework */,
|
||||
4BE2D324B040DCA2629C110D /* Pods_JellyfinPlayer_tvOS.framework */,
|
||||
59AFF849629F3C787909A911 /* Pods_WidgetExtension.framework */,
|
||||
);
|
||||
name = Frameworks;
|
||||
sourceTree = "<group>";
|
||||
|
@ -1062,6 +1073,14 @@
|
|||
path = Extensions;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
6286F09F271C0AA500C40ED5 /* Generated */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
6264E88B273850380081A12A /* Strings.swift */,
|
||||
);
|
||||
path = Generated;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
628B95252670CABD0091AF3B /* WidgetExtension */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
|
@ -1128,10 +1147,12 @@
|
|||
C78797A232E2B8774099D1E9 /* Pods */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
3773C07648173CE7FEC083D5 /* Pods-JellyfinPlayer iOS.debug.xcconfig */,
|
||||
BEEC50E7EFD4848C0E320941 /* Pods-JellyfinPlayer iOS.release.xcconfig */,
|
||||
DE5004F745B19E28744A7DE7 /* Pods-JellyfinPlayer tvOS.debug.xcconfig */,
|
||||
D79953919FED0C4DF72BA578 /* Pods-JellyfinPlayer tvOS.release.xcconfig */,
|
||||
772F6DAB8534FD1DB45B7687 /* Pods-JellyfinPlayer iOS.debug.xcconfig */,
|
||||
14E199C7BBA98782CAD2F0D4 /* Pods-JellyfinPlayer iOS.release.xcconfig */,
|
||||
B598C62749E5EFD37280FCC3 /* Pods-JellyfinPlayer tvOS.debug.xcconfig */,
|
||||
20CA36DDD247EED8D16438A5 /* Pods-JellyfinPlayer tvOS.release.xcconfig */,
|
||||
4BDCEE3B49CF70A9E9BA3CD8 /* Pods-WidgetExtension.debug.xcconfig */,
|
||||
FDEDADB92FA8523BC8432E45 /* Pods-WidgetExtension.release.xcconfig */,
|
||||
);
|
||||
path = Pods;
|
||||
sourceTree = "<group>";
|
||||
|
@ -1330,11 +1351,12 @@
|
|||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = 535870712669D21700D05A09 /* Build configuration list for PBXNativeTarget "JellyfinPlayer tvOS" */;
|
||||
buildPhases = (
|
||||
E7370E1AA68C6CB254E46F2C /* [CP] Check Pods Manifest.lock */,
|
||||
3D0F2756C71CDF6B9EEBD4E0 /* [CP] Check Pods Manifest.lock */,
|
||||
6286F0A3271C0ABA00C40ED5 /* R.swift */,
|
||||
5358705C2669D21600D05A09 /* Sources */,
|
||||
5358705D2669D21600D05A09 /* Frameworks */,
|
||||
5358705E2669D21600D05A09 /* Resources */,
|
||||
6AB6F1DD2C8AD942F71C8A32 /* [CP] Embed Pods Frameworks */,
|
||||
879C22C1CCC48E68C86E904C /* [CP] Embed Pods Frameworks */,
|
||||
);
|
||||
buildRules = (
|
||||
);
|
||||
|
@ -1362,19 +1384,20 @@
|
|||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = 5377CC1B263B596B003A4E83 /* Build configuration list for PBXNativeTarget "JellyfinPlayer iOS" */;
|
||||
buildPhases = (
|
||||
6435C3C2E610FE34AD537AC1 /* [CP] Check Pods Manifest.lock */,
|
||||
1C7487D3432E90546DA855B5 /* [CP] Check Pods Manifest.lock */,
|
||||
6286F09E271C093000C40ED5 /* R.swift */,
|
||||
5377CBED263B596A003A4E83 /* Sources */,
|
||||
5377CBEE263B596A003A4E83 /* Frameworks */,
|
||||
5377CBEF263B596A003A4E83 /* Resources */,
|
||||
5302F8322658B74800647A2E /* CopyFiles */,
|
||||
628B95312670CABE0091AF3B /* Embed App Extensions */,
|
||||
E8DDF21F62DFCE8CE76666BA /* [CP] Embed Pods Frameworks */,
|
||||
83FD120CA10FD0E91DAD83C9 /* [CP] Copy Pods Resources */,
|
||||
8D1E0C963DCE6C6F328B3EBB /* [CP] Embed Pods Frameworks */,
|
||||
DB8CA7C37DF78BEDCE4E37C1 /* [CP] Copy Pods Resources */,
|
||||
);
|
||||
buildRules = (
|
||||
);
|
||||
dependencies = (
|
||||
628B952C2670CABE0091AF3B /* PBXTargetDependency */,
|
||||
6264E889273848760081A12A /* PBXTargetDependency */,
|
||||
);
|
||||
name = "JellyfinPlayer iOS";
|
||||
packageProductDependencies = (
|
||||
|
@ -1398,6 +1421,7 @@
|
|||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = 628B952E2670CABE0091AF3B /* Build configuration list for PBXNativeTarget "WidgetExtension" */;
|
||||
buildPhases = (
|
||||
D4D3981ADF75BCD341D590C0 /* [CP] Check Pods Manifest.lock */,
|
||||
628B951C2670CABD0091AF3B /* Sources */,
|
||||
628B951D2670CABD0091AF3B /* Frameworks */,
|
||||
628B951E2670CABD0091AF3B /* Resources */,
|
||||
|
@ -1572,7 +1596,7 @@
|
|||
/* End PBXResourcesBuildPhase section */
|
||||
|
||||
/* Begin PBXShellScriptBuildPhase section */
|
||||
6435C3C2E610FE34AD537AC1 /* [CP] Check Pods Manifest.lock */ = {
|
||||
1C7487D3432E90546DA855B5 /* [CP] Check Pods Manifest.lock */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
|
@ -1594,41 +1618,7 @@
|
|||
shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
|
||||
showEnvVarsInLog = 0;
|
||||
};
|
||||
6AB6F1DD2C8AD942F71C8A32 /* [CP] Embed Pods Frameworks */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
inputFileListPaths = (
|
||||
"${PODS_ROOT}/Target Support Files/Pods-JellyfinPlayer tvOS/Pods-JellyfinPlayer tvOS-frameworks-${CONFIGURATION}-input-files.xcfilelist",
|
||||
);
|
||||
name = "[CP] Embed Pods Frameworks";
|
||||
outputFileListPaths = (
|
||||
"${PODS_ROOT}/Target Support Files/Pods-JellyfinPlayer tvOS/Pods-JellyfinPlayer tvOS-frameworks-${CONFIGURATION}-output-files.xcfilelist",
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-JellyfinPlayer tvOS/Pods-JellyfinPlayer tvOS-frameworks.sh\"\n";
|
||||
showEnvVarsInLog = 0;
|
||||
};
|
||||
83FD120CA10FD0E91DAD83C9 /* [CP] Copy Pods Resources */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
inputFileListPaths = (
|
||||
"${PODS_ROOT}/Target Support Files/Pods-JellyfinPlayer iOS/Pods-JellyfinPlayer iOS-resources-${CONFIGURATION}-input-files.xcfilelist",
|
||||
);
|
||||
name = "[CP] Copy Pods Resources";
|
||||
outputFileListPaths = (
|
||||
"${PODS_ROOT}/Target Support Files/Pods-JellyfinPlayer iOS/Pods-JellyfinPlayer iOS-resources-${CONFIGURATION}-output-files.xcfilelist",
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-JellyfinPlayer iOS/Pods-JellyfinPlayer iOS-resources.sh\"\n";
|
||||
showEnvVarsInLog = 0;
|
||||
};
|
||||
E7370E1AA68C6CB254E46F2C /* [CP] Check Pods Manifest.lock */ = {
|
||||
3D0F2756C71CDF6B9EEBD4E0 /* [CP] Check Pods Manifest.lock */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
|
@ -1650,7 +1640,60 @@
|
|||
shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
|
||||
showEnvVarsInLog = 0;
|
||||
};
|
||||
E8DDF21F62DFCE8CE76666BA /* [CP] Embed Pods Frameworks */ = {
|
||||
6286F09E271C093000C40ED5 /* R.swift */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
inputFileListPaths = (
|
||||
);
|
||||
inputPaths = (
|
||||
);
|
||||
name = R.swift;
|
||||
outputFileListPaths = (
|
||||
);
|
||||
outputPaths = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "# Type a script or drag a script file from your workspace to insert its path.\n\"${PROJECT_DIR}/bin/swiftgen\"\n";
|
||||
};
|
||||
6286F0A3271C0ABA00C40ED5 /* R.swift */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
inputFileListPaths = (
|
||||
);
|
||||
inputPaths = (
|
||||
);
|
||||
name = R.swift;
|
||||
outputFileListPaths = (
|
||||
);
|
||||
outputPaths = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "# Type a script or drag a script file from your workspace to insert its path.\n\"${PROJECT_DIR}/bin/swiftgen\"\n";
|
||||
};
|
||||
879C22C1CCC48E68C86E904C /* [CP] Embed Pods Frameworks */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
inputFileListPaths = (
|
||||
"${PODS_ROOT}/Target Support Files/Pods-JellyfinPlayer tvOS/Pods-JellyfinPlayer tvOS-frameworks-${CONFIGURATION}-input-files.xcfilelist",
|
||||
);
|
||||
name = "[CP] Embed Pods Frameworks";
|
||||
outputFileListPaths = (
|
||||
"${PODS_ROOT}/Target Support Files/Pods-JellyfinPlayer tvOS/Pods-JellyfinPlayer tvOS-frameworks-${CONFIGURATION}-output-files.xcfilelist",
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-JellyfinPlayer tvOS/Pods-JellyfinPlayer tvOS-frameworks.sh\"\n";
|
||||
showEnvVarsInLog = 0;
|
||||
};
|
||||
8D1E0C963DCE6C6F328B3EBB /* [CP] Embed Pods Frameworks */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
|
@ -1667,6 +1710,45 @@
|
|||
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-JellyfinPlayer iOS/Pods-JellyfinPlayer iOS-frameworks.sh\"\n";
|
||||
showEnvVarsInLog = 0;
|
||||
};
|
||||
D4D3981ADF75BCD341D590C0 /* [CP] Check Pods Manifest.lock */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
inputFileListPaths = (
|
||||
);
|
||||
inputPaths = (
|
||||
"${PODS_PODFILE_DIR_PATH}/Podfile.lock",
|
||||
"${PODS_ROOT}/Manifest.lock",
|
||||
);
|
||||
name = "[CP] Check Pods Manifest.lock";
|
||||
outputFileListPaths = (
|
||||
);
|
||||
outputPaths = (
|
||||
"$(DERIVED_FILE_DIR)/Pods-WidgetExtension-checkManifestLockResult.txt",
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
|
||||
showEnvVarsInLog = 0;
|
||||
};
|
||||
DB8CA7C37DF78BEDCE4E37C1 /* [CP] Copy Pods Resources */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
inputFileListPaths = (
|
||||
"${PODS_ROOT}/Target Support Files/Pods-JellyfinPlayer iOS/Pods-JellyfinPlayer iOS-resources-${CONFIGURATION}-input-files.xcfilelist",
|
||||
);
|
||||
name = "[CP] Copy Pods Resources";
|
||||
outputFileListPaths = (
|
||||
"${PODS_ROOT}/Target Support Files/Pods-JellyfinPlayer iOS/Pods-JellyfinPlayer iOS-resources-${CONFIGURATION}-output-files.xcfilelist",
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-JellyfinPlayer iOS/Pods-JellyfinPlayer iOS-resources.sh\"\n";
|
||||
showEnvVarsInLog = 0;
|
||||
};
|
||||
/* End PBXShellScriptBuildPhase section */
|
||||
|
||||
/* Begin PBXSourcesBuildPhase section */
|
||||
|
@ -1770,6 +1852,7 @@
|
|||
5321753E2671DE9C005491E6 /* Typings.swift in Sources */,
|
||||
E1F0204F26CCCA74001C1C3B /* VideoPlayerJumpLength.swift in Sources */,
|
||||
53ABFDEB2679753200886593 /* ConnectToServerView.swift in Sources */,
|
||||
6264E88D273850380081A12A /* Strings.swift in Sources */,
|
||||
536D3D76267BA9BB0004248C /* MainTabViewModel.swift in Sources */,
|
||||
E193D5512719432400900D82 /* ServerDetailViewModel.swift in Sources */,
|
||||
5310695C2684E7EE00CFFDBA /* VideoPlayerViewController.swift in Sources */,
|
||||
|
@ -1841,6 +1924,7 @@
|
|||
E173DA5226D04AAF00CC4EB7 /* ColorExtension.swift in Sources */,
|
||||
53892770263C25230035E14B /* NextUpView.swift in Sources */,
|
||||
E11D224227378428003F9CB3 /* ServerDetailCoordinator.swift in Sources */,
|
||||
6264E88C273850380081A12A /* Strings.swift in Sources */,
|
||||
C4BE0766271FC109003F4AD1 /* TVLibrariesViewModel.swift in Sources */,
|
||||
62ECA01826FA685A00E8EBB7 /* DeepLink.swift in Sources */,
|
||||
535BAEA5264A151C005FA86D /* VideoPlayer.swift in Sources */,
|
||||
|
@ -1929,6 +2013,7 @@
|
|||
files = (
|
||||
53649AB3269D3F5B00A2D8B7 /* LogManager.swift in Sources */,
|
||||
E13DD3CB27164BA8009D4DAF /* UIDeviceExtensions.swift in Sources */,
|
||||
6264E88A27384A6F0081A12A /* NetworkError.swift in Sources */,
|
||||
E19169D0272514760085832A /* HTTPScheme.swift in Sources */,
|
||||
6267B3D726710B9700A7371D /* CollectionExtensions.swift in Sources */,
|
||||
628B953C2670D2430091AF3B /* StringExtensions.swift in Sources */,
|
||||
|
@ -1936,6 +2021,7 @@
|
|||
E1AD105926D9A543003E4A08 /* LazyView.swift in Sources */,
|
||||
E11B1B6E2718CDBA006DA3E8 /* JellyfinAPIError.swift in Sources */,
|
||||
628B95372670CB800091AF3B /* JellyfinWidget.swift in Sources */,
|
||||
6264E88E273850380081A12A /* Strings.swift in Sources */,
|
||||
E1AD105426D97161003E4A08 /* BaseItemDtoExtensions.swift in Sources */,
|
||||
E1FCD09A26C4F35A007C8DCF /* ErrorMessage.swift in Sources */,
|
||||
628B95272670CABD0091AF3B /* NextUpWidget.swift in Sources */,
|
||||
|
@ -1943,7 +2029,6 @@
|
|||
E1D4BF8D2719F3A300A11E64 /* VideoPlayerJumpLength.swift in Sources */,
|
||||
6220D0AF26D5EABE00B8E046 /* ViewExtensions.swift in Sources */,
|
||||
E13DD3D7271693CD009D4DAF /* SwiftfinStoreDefaults.swift in Sources */,
|
||||
E1FCD09926C4F358007C8DCF /* NetworkError.swift in Sources */,
|
||||
E131691926C583BC0074BFEE /* LogConstructor.swift in Sources */,
|
||||
E13DD3CA27164B80009D4DAF /* SwiftfinStore.swift in Sources */,
|
||||
62EC353226766849000E9F2D /* SessionManager.swift in Sources */,
|
||||
|
@ -1955,10 +2040,10 @@
|
|||
/* End PBXSourcesBuildPhase section */
|
||||
|
||||
/* Begin PBXTargetDependency section */
|
||||
628B952C2670CABE0091AF3B /* PBXTargetDependency */ = {
|
||||
6264E889273848760081A12A /* PBXTargetDependency */ = {
|
||||
isa = PBXTargetDependency;
|
||||
target = 628B951F2670CABD0091AF3B /* WidgetExtension */;
|
||||
targetProxy = 628B952B2670CABE0091AF3B /* PBXContainerItemProxy */;
|
||||
targetProxy = 6264E888273848760081A12A /* PBXContainerItemProxy */;
|
||||
};
|
||||
/* End PBXTargetDependency section */
|
||||
|
||||
|
@ -2096,7 +2181,7 @@
|
|||
/* Begin XCBuildConfiguration section */
|
||||
535870722669D21700D05A09 /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = DE5004F745B19E28744A7DE7 /* Pods-JellyfinPlayer tvOS.debug.xcconfig */;
|
||||
baseConfigurationReference = B598C62749E5EFD37280FCC3 /* Pods-JellyfinPlayer tvOS.debug.xcconfig */;
|
||||
buildSettings = {
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = "Dev App Icon & Top Shelf Image";
|
||||
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
|
||||
|
@ -2126,7 +2211,7 @@
|
|||
};
|
||||
535870732669D21700D05A09 /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = D79953919FED0C4DF72BA578 /* Pods-JellyfinPlayer tvOS.release.xcconfig */;
|
||||
baseConfigurationReference = 20CA36DDD247EED8D16438A5 /* Pods-JellyfinPlayer tvOS.release.xcconfig */;
|
||||
buildSettings = {
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = "App Icon & Top Shelf Image";
|
||||
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
|
||||
|
@ -2276,7 +2361,7 @@
|
|||
};
|
||||
5377CC1C263B596B003A4E83 /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = 3773C07648173CE7FEC083D5 /* Pods-JellyfinPlayer iOS.debug.xcconfig */;
|
||||
baseConfigurationReference = 772F6DAB8534FD1DB45B7687 /* Pods-JellyfinPlayer iOS.debug.xcconfig */;
|
||||
buildSettings = {
|
||||
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = "AppIcon-Dev";
|
||||
|
@ -2312,7 +2397,7 @@
|
|||
};
|
||||
5377CC1D263B596B003A4E83 /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = BEEC50E7EFD4848C0E320941 /* Pods-JellyfinPlayer iOS.release.xcconfig */;
|
||||
baseConfigurationReference = 14E199C7BBA98782CAD2F0D4 /* Pods-JellyfinPlayer iOS.release.xcconfig */;
|
||||
buildSettings = {
|
||||
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
|
@ -2348,6 +2433,7 @@
|
|||
};
|
||||
628B952F2670CABE0091AF3B /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = 4BDCEE3B49CF70A9E9BA3CD8 /* Pods-WidgetExtension.debug.xcconfig */;
|
||||
buildSettings = {
|
||||
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
|
||||
ASSETCATALOG_COMPILER_WIDGET_BACKGROUND_COLOR_NAME = WidgetBackground;
|
||||
|
@ -2374,6 +2460,7 @@
|
|||
};
|
||||
628B95302670CABE0091AF3B /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = FDEDADB92FA8523BC8432E45 /* Pods-WidgetExtension.release.xcconfig */;
|
||||
buildSettings = {
|
||||
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
|
||||
ASSETCATALOG_COMPILER_WIDGET_BACKGROUND_COLOR_NAME = WidgetBackground;
|
||||
|
|
|
@ -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>DisableBuildSystemDeprecationDiagnostic</key>
|
||||
<true/>
|
||||
<key>PreviewsEnabled</key>
|
||||
<false/>
|
||||
</dict>
|
||||
</plist>
|
|
@ -13,10 +13,10 @@ import UIKit
|
|||
class AppDelegate: NSObject, UIApplicationDelegate {
|
||||
static var orientationLock = UIInterfaceOrientationMask.all
|
||||
|
||||
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool {
|
||||
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? = nil) -> Bool {
|
||||
|
||||
// Lazily initialize datastack
|
||||
let _ = SwiftfinStore.dataStack
|
||||
_ = SwiftfinStore.dataStack
|
||||
|
||||
return true
|
||||
}
|
||||
|
|
|
@ -77,8 +77,7 @@ extension AppURLHandler {
|
|||
// /Users/{UserID}/Items/{ItemID}
|
||||
if url.pathComponents[safe: 2]?.lowercased() == "items",
|
||||
let userID = url.pathComponents[safe: 1],
|
||||
let itemID = url.pathComponents[safe: 3]
|
||||
{
|
||||
let itemID = url.pathComponents[safe: 3] {
|
||||
// It would be nice if the ItemViewModel could be initialized to id later.
|
||||
getItem(userID: userID, itemID: itemID) { item in
|
||||
guard let item = item else { return }
|
||||
|
|
|
@ -75,7 +75,7 @@ struct PortraitItemView: View {
|
|||
.font(.caption)
|
||||
.fontWeight(.medium)
|
||||
} else {
|
||||
Text("S\(String(item.parentIndexNumber ?? 0)):E\(String(item.indexNumber ?? 0))")
|
||||
Text(L10n.seasonAndEpisode(String(item.parentIndexNumber ?? 0), String(item.indexNumber ?? 0)))
|
||||
.foregroundColor(.secondary)
|
||||
.font(.caption)
|
||||
.fontWeight(.medium)
|
||||
|
|
|
@ -23,7 +23,7 @@ struct BasicAppSettingsView: View {
|
|||
var body: some View {
|
||||
Form {
|
||||
Section {
|
||||
Picker(NSLocalizedString("Appearance", comment: ""), selection: $appAppearance) {
|
||||
Picker(L10n.appearance, selection: $appAppearance) {
|
||||
ForEach(self.viewModel.appearances, id: \.self) { appearance in
|
||||
Text(appearance.localizedName).tag(appearance.rawValue)
|
||||
}
|
||||
|
@ -31,7 +31,7 @@ struct BasicAppSettingsView: View {
|
|||
UIApplication.shared.windows.first?.overrideUserInterfaceStyle = appAppearance.style
|
||||
})
|
||||
} header: {
|
||||
Text("Accessibility")
|
||||
L10n.accessibility.text
|
||||
}
|
||||
|
||||
Section {
|
||||
|
@ -47,15 +47,15 @@ struct BasicAppSettingsView: View {
|
|||
Button {
|
||||
resetTapped = true
|
||||
} label: {
|
||||
Text("Reset")
|
||||
L10n.reset.text
|
||||
}
|
||||
}
|
||||
.alert("Reset", isPresented: $resetTapped, actions: {
|
||||
.alert(L10n.reset, isPresented: $resetTapped, actions: {
|
||||
Button(role: .destructive) {
|
||||
viewModel.reset()
|
||||
basicAppSettingsRouter.dismissCoordinator()
|
||||
} label: {
|
||||
Text("Reset")
|
||||
L10n.reset.text
|
||||
}
|
||||
})
|
||||
.navigationBarTitle("Settings", displayMode: .inline)
|
||||
|
|
|
@ -20,7 +20,7 @@ struct ConnectToServerView: View {
|
|||
var body: some View {
|
||||
List {
|
||||
Section {
|
||||
TextField(NSLocalizedString("Server URL", comment: ""), text: $uri)
|
||||
TextField(L10n.serverURL, text: $uri)
|
||||
.disableAutocorrection(true)
|
||||
.autocapitalization(.none)
|
||||
.keyboardType(.URL)
|
||||
|
@ -40,7 +40,7 @@ struct ConnectToServerView: View {
|
|||
Button {
|
||||
viewModel.connectToServer(uri: uri)
|
||||
} label: {
|
||||
Text("Connect")
|
||||
L10n.connect.text
|
||||
}
|
||||
.disabled(uri.isEmpty)
|
||||
}
|
||||
|
@ -88,7 +88,7 @@ struct ConnectToServerView: View {
|
|||
}
|
||||
} header: {
|
||||
HStack {
|
||||
Text("Local Servers")
|
||||
L10n.localServers.text
|
||||
Spacer()
|
||||
|
||||
Button {
|
||||
|
@ -114,7 +114,7 @@ struct ConnectToServerView: View {
|
|||
}),
|
||||
secondaryButton: .cancel())
|
||||
}
|
||||
.navigationTitle("Connect")
|
||||
.navigationTitle(L10n.connect)
|
||||
.onAppear {
|
||||
viewModel.discoverServers()
|
||||
AppURLHandler.shared.appURLState = .allowedInLogin
|
||||
|
|
|
@ -34,7 +34,7 @@ struct HomeView: View {
|
|||
|
||||
ForEach(viewModel.libraries, id: \.self) { library in
|
||||
HStack {
|
||||
Text("Latest \(library.name ?? "")")
|
||||
Text(L10n.latestWithString(library.name ?? ""))
|
||||
.font(.title2)
|
||||
.fontWeight(.bold)
|
||||
Spacer()
|
||||
|
@ -45,7 +45,7 @@ struct HomeView: View {
|
|||
title: library.name ?? ""))
|
||||
} label: {
|
||||
HStack {
|
||||
Text("See All").font(.subheadline).fontWeight(.bold)
|
||||
L10n.seeAll.text.font(.subheadline).fontWeight(.bold)
|
||||
Image(systemName: "chevron.right").font(Font.subheadline.bold())
|
||||
}
|
||||
}
|
||||
|
@ -70,7 +70,7 @@ struct HomeView: View {
|
|||
|
||||
var body: some View {
|
||||
innerBody
|
||||
.navigationTitle(NSLocalizedString("Home", comment: ""))
|
||||
.navigationTitle(L10n.home)
|
||||
.toolbar {
|
||||
ToolbarItemGroup(placement: .navigationBarTrailing) {
|
||||
Button {
|
||||
|
|
|
@ -28,7 +28,7 @@ struct ItemNavigationView: View {
|
|||
}
|
||||
}
|
||||
|
||||
fileprivate struct ItemView: View {
|
||||
private struct ItemView: View {
|
||||
@EnvironmentObject var itemRouter: ItemCoordinator.Router
|
||||
|
||||
@State private var videoIsLoading: Bool = false // This variable is only changed by the underlying VLC view.
|
||||
|
|
|
@ -29,7 +29,7 @@ struct ItemViewBody: View {
|
|||
PortraitImageHStackView(items: seriesViewModel.seasons,
|
||||
maxWidth: 150,
|
||||
topBarView: {
|
||||
Text("Seasons")
|
||||
L10n.seasons.text
|
||||
.font(.callout)
|
||||
.fontWeight(.semibold)
|
||||
.padding(.top, 3)
|
||||
|
@ -41,7 +41,7 @@ struct ItemViewBody: View {
|
|||
|
||||
// MARK: Genres
|
||||
|
||||
PillHStackView(title: "Genres",
|
||||
PillHStackView(title: L10n.genres,
|
||||
items: viewModel.item.genreItems ?? [],
|
||||
selectedAction: { genre in
|
||||
itemRouter.route(to: \.library, (viewModel: .init(genre: genre), title: genre.title))
|
||||
|
@ -50,7 +50,7 @@ struct ItemViewBody: View {
|
|||
// MARK: Studios
|
||||
|
||||
if let studios = viewModel.item.studios {
|
||||
PillHStackView(title: "Studios",
|
||||
PillHStackView(title: L10n.studios,
|
||||
items: studios) { studio in
|
||||
itemRouter.route(to: \.library, (viewModel: .init(studio: studio), title: studio.name ?? ""))
|
||||
}
|
||||
|
@ -79,7 +79,7 @@ struct ItemViewBody: View {
|
|||
PortraitImageHStackView(items: viewModel.similarItems,
|
||||
maxWidth: 150,
|
||||
topBarView: {
|
||||
Text("More Like This")
|
||||
L10n.moreLikeThis.text
|
||||
.font(.callout)
|
||||
.fontWeight(.semibold)
|
||||
.padding(.top, 3)
|
||||
|
|
|
@ -31,32 +31,32 @@ struct LibraryFilterView: View {
|
|||
} else {
|
||||
Form {
|
||||
if viewModel.enabledFilterType.contains(.genre) {
|
||||
MultiSelector(label: NSLocalizedString("Genres", comment: ""),
|
||||
MultiSelector(label: L10n.genres,
|
||||
options: viewModel.possibleGenres,
|
||||
optionToString: { $0.name ?? "" },
|
||||
selected: $viewModel.modifiedFilters.withGenres)
|
||||
}
|
||||
if viewModel.enabledFilterType.contains(.filter) {
|
||||
MultiSelector(label: NSLocalizedString("Filters", comment: ""),
|
||||
MultiSelector(label: L10n.filters,
|
||||
options: viewModel.possibleItemFilters,
|
||||
optionToString: { $0.localized },
|
||||
selected: $viewModel.modifiedFilters.filters)
|
||||
}
|
||||
if viewModel.enabledFilterType.contains(.tag) {
|
||||
MultiSelector(label: NSLocalizedString("Tags", comment: ""),
|
||||
MultiSelector(label: L10n.tags,
|
||||
options: viewModel.possibleTags,
|
||||
optionToString: { $0 },
|
||||
selected: $viewModel.modifiedFilters.tags)
|
||||
}
|
||||
if viewModel.enabledFilterType.contains(.sortBy) {
|
||||
Picker(selection: $viewModel.selectedSortBy, label: Text("Sort by")) {
|
||||
Picker(selection: $viewModel.selectedSortBy, label: L10n.sortBy.text) {
|
||||
ForEach(viewModel.possibleSortBys, id: \.self) { so in
|
||||
Text(so.localized).tag(so)
|
||||
}
|
||||
}
|
||||
}
|
||||
if viewModel.enabledFilterType.contains(.sortOrder) {
|
||||
Picker(selection: $viewModel.selectedSortOrder, label: Text("Display order")) {
|
||||
Picker(selection: $viewModel.selectedSortOrder, label: L10n.displayOrder.text) {
|
||||
ForEach(viewModel.possibleSortOrders, id: \.self) { so in
|
||||
Text(so.rawValue).tag(so)
|
||||
}
|
||||
|
@ -68,11 +68,11 @@ struct LibraryFilterView: View {
|
|||
self.filters = viewModel.modifiedFilters
|
||||
filterRouter.dismissCoordinator()
|
||||
} label: {
|
||||
Text("Reset")
|
||||
L10n.reset.text
|
||||
}
|
||||
}
|
||||
}
|
||||
.navigationBarTitle(NSLocalizedString("Filter Results", comment: ""), displayMode: .inline)
|
||||
.navigationBarTitle(L10n.filterResults, displayMode: .inline)
|
||||
.toolbar {
|
||||
ToolbarItemGroup(placement: .navigationBarLeading) {
|
||||
Button {
|
||||
|
@ -87,7 +87,7 @@ struct LibraryFilterView: View {
|
|||
self.filters = viewModel.modifiedFilters
|
||||
filterRouter.dismissCoordinator()
|
||||
} label: {
|
||||
Text("Apply")
|
||||
L10n.apply.text
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -23,7 +23,7 @@ struct LibraryListView: View {
|
|||
ZStack {
|
||||
HStack {
|
||||
Spacer()
|
||||
Text("Your Favorites")
|
||||
L10n.yourFavorites.text
|
||||
.foregroundColor(.black)
|
||||
.font(.subheadline)
|
||||
.fontWeight(.semibold)
|
||||
|
@ -39,12 +39,12 @@ struct LibraryListView: View {
|
|||
.padding(.bottom, 5)
|
||||
|
||||
NavigationLink(destination: LazyView {
|
||||
Text("WIP")
|
||||
L10n.wip.text
|
||||
}) {
|
||||
ZStack {
|
||||
HStack {
|
||||
Spacer()
|
||||
Text("All Genres")
|
||||
L10n.allGenres.text
|
||||
.foregroundColor(.black)
|
||||
.font(.subheadline)
|
||||
.fontWeight(.semibold)
|
||||
|
@ -98,7 +98,7 @@ struct LibraryListView: View {
|
|||
.padding(.trailing, 16)
|
||||
.padding(.top, 8)
|
||||
}
|
||||
.navigationTitle(NSLocalizedString("All Media", comment: ""))
|
||||
.navigationTitle(L10n.allMedia)
|
||||
.toolbar {
|
||||
ToolbarItemGroup(placement: .navigationBarTrailing) {
|
||||
Button {
|
||||
|
|
|
@ -46,7 +46,7 @@ struct LibrarySearchView: View {
|
|||
var suggestionsListView: some View {
|
||||
ScrollView {
|
||||
LazyVStack(spacing: 8) {
|
||||
Text("Suggestions")
|
||||
L10n.suggestions.text
|
||||
.font(.headline)
|
||||
.fontWeight(.bold)
|
||||
.foregroundColor(.primary)
|
||||
|
|
|
@ -55,7 +55,7 @@ struct LibraryView: View {
|
|||
Image(systemName: "chevron.left")
|
||||
.font(.system(size: 25))
|
||||
}.disabled(!viewModel.hasPreviousPage)
|
||||
Text("Page \(String(viewModel.currentPage + 1)) of \(String(viewModel.totalPages))")
|
||||
Text(L10n.pageOfWithNumbers(String(viewModel.currentPage + 1), String(viewModel.totalPages)))
|
||||
.font(.subheadline)
|
||||
.fontWeight(.medium)
|
||||
Button {
|
||||
|
@ -72,7 +72,7 @@ struct LibraryView: View {
|
|||
}
|
||||
}
|
||||
} else {
|
||||
Text("No results.")
|
||||
L10n.noResults.text
|
||||
}
|
||||
}
|
||||
.navigationBarTitle(title, displayMode: .inline)
|
||||
|
|
|
@ -32,7 +32,7 @@ struct LoadingView<Content>: View where Content: View {
|
|||
// indicator, with some text underneath showing what we are doing
|
||||
HStack {
|
||||
ProgressView()
|
||||
Text(text ?? "Loading").fontWeight(.semibold).font(.callout).offset(x: 60)
|
||||
Text(text ?? L10n.loading).fontWeight(.semibold).font(.callout).offset(x: 60)
|
||||
Spacer()
|
||||
}
|
||||
.padding(EdgeInsets(top: 20, leading: 20, bottom: 20, trailing: 10))
|
||||
|
@ -70,7 +70,7 @@ struct LoadingViewNoBlur<Content>: View where Content: View {
|
|||
// indicator, with some text underneath showing what we are doing
|
||||
HStack {
|
||||
ProgressView()
|
||||
Text(text ?? "Loading").fontWeight(.semibold).font(.callout).offset(x: 60)
|
||||
Text(text ?? L10n.loading).fontWeight(.semibold).font(.callout).offset(x: 60)
|
||||
Spacer()
|
||||
}
|
||||
.padding(EdgeInsets(top: 20, leading: 20, bottom: 20, trailing: 10))
|
||||
|
|
|
@ -17,7 +17,7 @@ struct NextUpView: View {
|
|||
|
||||
var body: some View {
|
||||
VStack(alignment: .leading) {
|
||||
Text("Next Up")
|
||||
L10n.nextUp.text
|
||||
.font(.title2)
|
||||
.fontWeight(.bold)
|
||||
.padding(.leading, 16)
|
||||
|
|
|
@ -81,7 +81,7 @@ struct ServerListView: View {
|
|||
.padding(.horizontal, 30)
|
||||
.padding([.top, .bottom], 20)
|
||||
|
||||
Text("Connect")
|
||||
L10n.connect.text
|
||||
.foregroundColor(Color.white)
|
||||
.bold()
|
||||
}
|
||||
|
|
|
@ -108,7 +108,7 @@ struct SettingsView: View {
|
|||
}
|
||||
}
|
||||
|
||||
Section(header: Text("Accessibility")) {
|
||||
Section(header: L10n.accessibility.text) {
|
||||
Toggle("Automatically show subtitles", isOn: $isAutoSelectSubtitles)
|
||||
SearchablePicker(label: "Preferred subtitle language",
|
||||
options: viewModel.langs,
|
||||
|
@ -129,7 +129,7 @@ struct SettingsView: View {
|
|||
.auto
|
||||
},
|
||||
set: { autoSelectAudioLangcode = $0.isoCode }))
|
||||
Picker(NSLocalizedString("Appearance", comment: ""), selection: $appAppearance) {
|
||||
Picker(L10n.appearance, selection: $appAppearance) {
|
||||
ForEach(self.viewModel.appearances, id: \.self) { appearance in
|
||||
Text(appearance.localizedName).tag(appearance.rawValue)
|
||||
}
|
||||
|
|
|
@ -20,11 +20,11 @@ struct UserSignInView: View {
|
|||
Form {
|
||||
|
||||
Section {
|
||||
TextField("Username", text: $username)
|
||||
TextField(L10n.username, text: $username)
|
||||
.disableAutocorrection(true)
|
||||
.autocapitalization(.none)
|
||||
|
||||
SecureField("Password", text: $password)
|
||||
SecureField(L10n.password, text: $password)
|
||||
.disableAutocorrection(true)
|
||||
.autocapitalization(.none)
|
||||
|
||||
|
|
|
@ -153,7 +153,7 @@ class PlayerViewController: UIViewController, GCKDiscoveryManagerListener, GCKRe
|
|||
sendProgressReport(eventName: "unpause")
|
||||
} else {
|
||||
sendJellyfinCommand(command: "Seek", options: [
|
||||
"position": Int(secondsScrubbedTo),
|
||||
"position": Int(secondsScrubbedTo)
|
||||
])
|
||||
}
|
||||
}
|
||||
|
@ -421,7 +421,7 @@ class PlayerViewController: UIViewController, GCKDiscoveryManagerListener, GCKRe
|
|||
if manifest.type == "Movie" {
|
||||
titleLabel.text = manifest.name ?? ""
|
||||
} else {
|
||||
titleLabel.text = "S\(String(manifest.parentIndexNumber ?? 0)):E\(String(manifest.indexNumber ?? 0)) “\(manifest.name ?? "")”"
|
||||
titleLabel.text = "\(L10n.seasonAndEpisode(String(manifest.parentIndexNumber ?? 0), String(manifest.indexNumber ?? 0))) “\(manifest.name ?? "")”"
|
||||
|
||||
setupNextUpView()
|
||||
upNextViewModel.delegate = self
|
||||
|
@ -664,8 +664,7 @@ class PlayerViewController: UIViewController, GCKDiscoveryManagerListener, GCKRe
|
|||
subtitleTrackArray.forEach { subtitle in
|
||||
if Defaults[.isAutoSelectSubtitles] {
|
||||
if Defaults[.autoSelectSubtitlesLangCode] == "Auto",
|
||||
subtitle.languageCode.contains(Locale.current.languageCode ?? "")
|
||||
{
|
||||
subtitle.languageCode.contains(Locale.current.languageCode ?? "") {
|
||||
selectedCaptionTrack = subtitle.id
|
||||
mediaPlayer.currentVideoSubTitleIndex = subtitle.id
|
||||
} else if subtitle.languageCode.contains(Defaults[.autoSelectSubtitlesLangCode]) {
|
||||
|
@ -816,7 +815,7 @@ class PlayerViewController: UIViewController, GCKDiscoveryManagerListener, GCKRe
|
|||
shouldShowLoadingScreen = true
|
||||
videoControlsView.isHidden = true
|
||||
|
||||
titleLabel.text = "S\(String(manifest.parentIndexNumber ?? 0)):E\(String(manifest.indexNumber ?? 0)) “\(manifest.name ?? "")”"
|
||||
titleLabel.text = "\(L10n.seasonAndEpisode(String(manifest.parentIndexNumber ?? 0), String(manifest.indexNumber ?? 0))) “\(manifest.name ?? "")”"
|
||||
|
||||
setupMediaPlayer()
|
||||
getNextEpisode()
|
||||
|
@ -854,7 +853,7 @@ extension PlayerViewController: GCKGenericChannelDelegate {
|
|||
if hasSentRemoteSeek == false {
|
||||
hasSentRemoteSeek = true
|
||||
sendJellyfinCommand(command: "Seek", options: [
|
||||
"position": Int(Float(manifest.runTimeTicks! / 10_000_000) * mediaPlayer.position),
|
||||
"position": Int(Float(manifest.runTimeTicks! / 10_000_000) * mediaPlayer.position)
|
||||
])
|
||||
}
|
||||
}
|
||||
|
@ -880,7 +879,7 @@ extension PlayerViewController: GCKGenericChannelDelegate {
|
|||
"serverId": SessionManager.main.currentLogin.server.id,
|
||||
"serverVersion": "10.8.0",
|
||||
"receiverName": castSessionManager.currentCastSession!.device.friendlyName!,
|
||||
"subtitleBurnIn": false,
|
||||
"subtitleBurnIn": false
|
||||
]
|
||||
let jsonData = JSON(payload)
|
||||
|
||||
|
@ -935,8 +934,8 @@ extension PlayerViewController: GCKSessionManagerListener {
|
|||
"Name": manifest.name!,
|
||||
"Type": manifest.type!,
|
||||
"MediaType": manifest.mediaType!,
|
||||
"IsFolder": manifest.isFolder!,
|
||||
]],
|
||||
"IsFolder": manifest.isFolder!
|
||||
]]
|
||||
]
|
||||
sendJellyfinCommand(command: "PlayNow", options: playNowOptions)
|
||||
}
|
||||
|
@ -1104,8 +1103,7 @@ struct VLCPlayerWithControls: UIViewControllerRepresentable {
|
|||
|
||||
typealias UIViewControllerType = PlayerViewController
|
||||
func makeUIViewController(context: UIViewControllerRepresentableContext<VLCPlayerWithControls>) -> VLCPlayerWithControls
|
||||
.UIViewControllerType
|
||||
{
|
||||
.UIViewControllerType {
|
||||
let storyboard = UIStoryboard(name: "VideoPlayer", bundle: nil)
|
||||
let customViewController = storyboard.instantiateViewController(withIdentifier: "VideoPlayer") as! PlayerViewController
|
||||
customViewController.manifest = item
|
||||
|
|
|
@ -56,7 +56,7 @@ struct VideoPlayerCastDeviceSelector: View {
|
|||
delegate?.castPopoverDismissed()
|
||||
} label: {
|
||||
HStack {
|
||||
Text("Connect")
|
||||
L10n.connect.text
|
||||
.font(.caption)
|
||||
.fontWeight(.medium)
|
||||
Image(systemName: "bonjour")
|
||||
|
@ -66,14 +66,14 @@ struct VideoPlayerCastDeviceSelector: View {
|
|||
}
|
||||
}
|
||||
} else {
|
||||
Text("No Cast devices found..")
|
||||
L10n.noCastdevicesfound.text
|
||||
.foregroundColor(.secondary)
|
||||
.font(.subheadline)
|
||||
.fontWeight(.medium)
|
||||
}
|
||||
}
|
||||
.navigationBarTitleDisplayMode(.inline)
|
||||
.navigationTitle(NSLocalizedString("Select Cast Destination", comment: ""))
|
||||
.navigationTitle(L10n.selectCastDestination)
|
||||
.toolbar {
|
||||
ToolbarItemGroup(placement: .navigationBarLeading) {
|
||||
if UIDevice.current.userInterfaceIdiom == .phone {
|
||||
|
@ -82,7 +82,7 @@ struct VideoPlayerCastDeviceSelector: View {
|
|||
} label: {
|
||||
HStack {
|
||||
Image(systemName: "chevron.left")
|
||||
Text("Back").font(.callout)
|
||||
L10n.back.text.font(.callout)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -40,7 +40,7 @@ struct VideoPlayerSettings: View {
|
|||
|
||||
var body: some View {
|
||||
Form {
|
||||
Picker(NSLocalizedString("Closed Captions", comment: ""), selection: $captionTrack) {
|
||||
Picker(L10n.closedCaptions, selection: $captionTrack) {
|
||||
ForEach(delegate.subtitleTrackArray, id: \.id) { caption in
|
||||
Text(caption.name).tag(caption.id)
|
||||
}
|
||||
|
@ -48,14 +48,14 @@ struct VideoPlayerSettings: View {
|
|||
.onChange(of: captionTrack) { track in
|
||||
self.delegate.subtitleTrackChanged(newTrackID: track)
|
||||
}
|
||||
Picker(NSLocalizedString("Audio Track", comment: ""), selection: $audioTrack) {
|
||||
Picker(L10n.audioTrack, selection: $audioTrack) {
|
||||
ForEach(delegate.audioTrackArray, id: \.id) { caption in
|
||||
Text(caption.name).tag(caption.id).lineLimit(1)
|
||||
}
|
||||
}.onChange(of: audioTrack) { track in
|
||||
self.delegate.audioTrackChanged(newTrackID: track)
|
||||
}
|
||||
Picker(NSLocalizedString("Playback Speed", comment: ""), selection: $playbackSpeedSelection) {
|
||||
Picker(L10n.playbackSpeed, selection: $playbackSpeedSelection) {
|
||||
ForEach(delegate.playbackSpeeds.indices, id: \.self) { speedIndex in
|
||||
let speed = delegate.playbackSpeeds[speedIndex]
|
||||
Text("\(String(speed))x").tag(speedIndex)
|
||||
|
@ -65,7 +65,7 @@ struct VideoPlayerSettings: View {
|
|||
self.delegate.playbackSpeedChanged(index: index)
|
||||
})
|
||||
}.navigationBarTitleDisplayMode(.inline)
|
||||
.navigationTitle(NSLocalizedString("Audio & Captions", comment: ""))
|
||||
.navigationTitle(L10n.audioAndCaptions)
|
||||
.toolbar {
|
||||
ToolbarItemGroup(placement: .navigationBarLeading) {
|
||||
if UIDevice.current.userInterfaceIdiom == .phone {
|
||||
|
@ -74,7 +74,7 @@ struct VideoPlayerSettings: View {
|
|||
} label: {
|
||||
HStack {
|
||||
Image(systemName: "chevron.left")
|
||||
Text("Back").font(.callout)
|
||||
L10n.back.text.font(.callout)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -32,7 +32,7 @@ struct VideoUpNextView: View {
|
|||
} label: {
|
||||
HStack {
|
||||
VStack {
|
||||
Text("Play Next")
|
||||
L10n.playNext.text
|
||||
.foregroundColor(.white)
|
||||
.font(.subheadline)
|
||||
.fontWeight(.semibold)
|
||||
|
|
13
Podfile
13
Podfile
|
@ -1,11 +1,20 @@
|
|||
use_frameworks!
|
||||
inhibit_all_warnings!
|
||||
def shared_pods
|
||||
pod 'SwiftGen'
|
||||
end
|
||||
|
||||
target 'JellyfinPlayer iOS' do
|
||||
platform :ios, '14.0'
|
||||
use_frameworks!
|
||||
shared_pods
|
||||
pod 'google-cast-sdk'
|
||||
pod 'MobileVLCKit'
|
||||
end
|
||||
target 'JellyfinPlayer tvOS' do
|
||||
platform :tvos, '14.0'
|
||||
use_frameworks!
|
||||
shared_pods
|
||||
pod 'TVVLCKit'
|
||||
end
|
||||
target 'WidgetExtension' do
|
||||
shared_pods
|
||||
end
|
|
@ -26,7 +26,7 @@ final class MainTabCoordinator: TabCoordinatable {
|
|||
|
||||
@ViewBuilder func makeHomeTab(isActive: Bool) -> some View {
|
||||
Image(systemName: "house")
|
||||
Text("Home")
|
||||
L10n.home.text
|
||||
}
|
||||
|
||||
func makeAllMedia() -> NavigationViewCoordinator<LibraryListCoordinator> {
|
||||
|
@ -35,7 +35,7 @@ final class MainTabCoordinator: TabCoordinatable {
|
|||
|
||||
@ViewBuilder func makeAllMediaTab(isActive: Bool) -> some View {
|
||||
Image(systemName: "folder")
|
||||
Text("All Media")
|
||||
L10n.allMedia.text
|
||||
}
|
||||
|
||||
@ViewBuilder func customize(_ view: AnyView) -> some View {
|
||||
|
|
|
@ -33,7 +33,7 @@ final class MainTabCoordinator: TabCoordinatable {
|
|||
@ViewBuilder func makeHomeTab(isActive: Bool) -> some View {
|
||||
HStack {
|
||||
Image(systemName: "house")
|
||||
Text("Home")
|
||||
L10n.home.text
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -85,13 +85,13 @@ enum NetworkError: Error {
|
|||
logMessage = "Cannot connect to host."
|
||||
logConstructor.message = logMessage
|
||||
errorMessage = ErrorMessage(code: err._code,
|
||||
title: "Error",
|
||||
title: L10n.error,
|
||||
displayMessage: displayMessage,
|
||||
logConstructor: logConstructor)
|
||||
default:
|
||||
logConstructor.message = logMessage
|
||||
errorMessage = ErrorMessage(code: err._code,
|
||||
title: "Error",
|
||||
title: L10n.error,
|
||||
displayMessage: displayMessage,
|
||||
logConstructor: logConstructor)
|
||||
}
|
||||
|
@ -111,7 +111,7 @@ enum NetworkError: Error {
|
|||
case .error:
|
||||
logConstructor.message = logMessage
|
||||
errorMessage = ErrorMessage(code: 0,
|
||||
title: "Error",
|
||||
title: L10n.error,
|
||||
displayMessage: displayMessage,
|
||||
logConstructor: logConstructor)
|
||||
}
|
||||
|
@ -140,7 +140,7 @@ enum NetworkError: Error {
|
|||
default:
|
||||
logConstructor.message = logMessage
|
||||
errorMessage = ErrorMessage(code: code,
|
||||
title: "Error",
|
||||
title: L10n.error,
|
||||
displayMessage: displayMessage,
|
||||
logConstructor: logConstructor)
|
||||
}
|
||||
|
|
|
@ -80,7 +80,7 @@ public extension BaseItemDto {
|
|||
|
||||
func getEpisodeLocator() -> String? {
|
||||
if let seasonNo = parentIndexNumber, let episodeNo = indexNumber {
|
||||
return "S\(seasonNo):E\(episodeNo)"
|
||||
return L10n.seasonAndEpisode(String(seasonNo), String(episodeNo))
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -29,7 +29,6 @@ extension BaseItemPerson {
|
|||
return imageBlurHashes?.primary?[imgTag] ?? "001fC^"
|
||||
}
|
||||
|
||||
|
||||
// MARK: First Role
|
||||
|
||||
// Jellyfin will grab all roles the person played in the show which makes the role
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
*/
|
||||
|
||||
import Foundation
|
||||
import SwiftUI
|
||||
|
||||
extension String {
|
||||
func removeRegexMatches(pattern: String, replaceWith: String = "") -> String {
|
||||
|
@ -31,4 +32,8 @@ extension String {
|
|||
|
||||
return "\(padString)\(self)"
|
||||
}
|
||||
|
||||
var text: Text {
|
||||
Text(self)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,184 @@
|
|||
// swiftlint:disable all
|
||||
// Generated using SwiftGen — https://github.com/SwiftGen/SwiftGen
|
||||
|
||||
import Foundation
|
||||
|
||||
// swiftlint:disable superfluous_disable_command file_length implicit_return
|
||||
|
||||
// MARK: - Strings
|
||||
|
||||
// swiftlint:disable explicit_type_interface function_parameter_count identifier_name line_length
|
||||
// swiftlint:disable nesting type_body_length type_name vertical_whitespace_opening_braces
|
||||
internal enum L10n {
|
||||
/// Accessibility
|
||||
internal static let accessibility = L10n.tr("Localizable", "accessibility")
|
||||
/// All Genres
|
||||
internal static let allGenres = L10n.tr("Localizable", "allGenres")
|
||||
/// All Media
|
||||
internal static let allMedia = L10n.tr("Localizable", "allMedia")
|
||||
/// Appearance
|
||||
internal static let appearance = L10n.tr("Localizable", "appearance")
|
||||
/// Apply
|
||||
internal static let apply = L10n.tr("Localizable", "apply")
|
||||
/// Audio & Captions
|
||||
internal static let audioAndCaptions = L10n.tr("Localizable", "audioAndCaptions")
|
||||
/// Audio Track
|
||||
internal static let audioTrack = L10n.tr("Localizable", "audioTrack")
|
||||
/// Back
|
||||
internal static let back = L10n.tr("Localizable", "back")
|
||||
/// CAST
|
||||
internal static let cast = L10n.tr("Localizable", "cast")
|
||||
/// Change Server
|
||||
internal static let changeServer = L10n.tr("Localizable", "changeServer")
|
||||
/// Closed Captions
|
||||
internal static let closedCaptions = L10n.tr("Localizable", "closedCaptions")
|
||||
/// Connect
|
||||
internal static let connect = L10n.tr("Localizable", "connect")
|
||||
/// Connect Manually
|
||||
internal static let connectManually = L10n.tr("Localizable", "connectManually")
|
||||
/// Connect to Jellyfin
|
||||
internal static let connectToJellyfin = L10n.tr("Localizable", "connectToJellyfin")
|
||||
/// Connect to Server
|
||||
internal static let connectToServer = L10n.tr("Localizable", "connectToServer")
|
||||
/// Continue Watching
|
||||
internal static let continueWatching = L10n.tr("Localizable", "continueWatching")
|
||||
/// Dark
|
||||
internal static let dark = L10n.tr("Localizable", "dark")
|
||||
/// DIRECTOR
|
||||
internal static let director = L10n.tr("Localizable", "director")
|
||||
/// Discovered Servers
|
||||
internal static let discoveredServers = L10n.tr("Localizable", "discoveredServers")
|
||||
/// Display order
|
||||
internal static let displayOrder = L10n.tr("Localizable", "displayOrder")
|
||||
/// Empty Next Up
|
||||
internal static let emptyNextUp = L10n.tr("Localizable", "emptyNextUp")
|
||||
/// Episodes
|
||||
internal static let episodes = L10n.tr("Localizable", "episodes")
|
||||
/// Error
|
||||
internal static let error = L10n.tr("Localizable", "error")
|
||||
/// Filter Results
|
||||
internal static let filterResults = L10n.tr("Localizable", "filterResults")
|
||||
/// Filters
|
||||
internal static let filters = L10n.tr("Localizable", "filters")
|
||||
/// Genres
|
||||
internal static let genres = L10n.tr("Localizable", "genres")
|
||||
/// Home
|
||||
internal static let home = L10n.tr("Localizable", "home")
|
||||
/// Latest %@
|
||||
internal static func latestWithString(_ p1: Any) -> String {
|
||||
return L10n.tr("Localizable", "latestWithString", String(describing: p1))
|
||||
}
|
||||
/// Library
|
||||
internal static let library = L10n.tr("Localizable", "library")
|
||||
/// Light
|
||||
internal static let light = L10n.tr("Localizable", "light")
|
||||
/// Loading
|
||||
internal static let loading = L10n.tr("Localizable", "loading")
|
||||
/// Local Servers
|
||||
internal static let localServers = L10n.tr("Localizable", "localServers")
|
||||
/// Login
|
||||
internal static let login = L10n.tr("Localizable", "login")
|
||||
/// Login to %@
|
||||
internal static func loginToWithString(_ p1: Any) -> String {
|
||||
return L10n.tr("Localizable", "loginToWithString", String(describing: p1))
|
||||
}
|
||||
/// More Like This
|
||||
internal static let moreLikeThis = L10n.tr("Localizable", "moreLikeThis")
|
||||
/// Next Up
|
||||
internal static let nextUp = L10n.tr("Localizable", "nextUp")
|
||||
/// No Cast devices found..
|
||||
internal static let noCastdevicesfound = L10n.tr("Localizable", "noCastdevicesfound")
|
||||
/// No results.
|
||||
internal static let noResults = L10n.tr("Localizable", "noResults")
|
||||
/// Type: %@ not implemented yet :(
|
||||
internal static func notImplementedYetWithType(_ p1: Any) -> String {
|
||||
return L10n.tr("Localizable", "notImplementedYetWithType", String(describing: p1))
|
||||
}
|
||||
/// Ok
|
||||
internal static let ok = L10n.tr("Localizable", "ok")
|
||||
/// Other User
|
||||
internal static let otherUser = L10n.tr("Localizable", "otherUser")
|
||||
/// Page %1$@ of %2$@
|
||||
internal static func pageOfWithNumbers(_ p1: Any, _ p2: Any) -> String {
|
||||
return L10n.tr("Localizable", "pageOfWithNumbers", String(describing: p1), String(describing: p2))
|
||||
}
|
||||
/// Password
|
||||
internal static let password = L10n.tr("Localizable", "password")
|
||||
/// Play
|
||||
internal static let play = L10n.tr("Localizable", "play")
|
||||
/// Playback settings
|
||||
internal static let playbackSettings = L10n.tr("Localizable", "playbackSettings")
|
||||
/// Playback Speed
|
||||
internal static let playbackSpeed = L10n.tr("Localizable", "playbackSpeed")
|
||||
/// Play Next
|
||||
internal static let playNext = L10n.tr("Localizable", "playNext")
|
||||
/// Reset
|
||||
internal static let reset = L10n.tr("Localizable", "reset")
|
||||
/// Search...
|
||||
internal static let search = L10n.tr("Localizable", "search")
|
||||
/// S%1$@:E%2$@
|
||||
internal static func seasonAndEpisode(_ p1: Any, _ p2: Any) -> String {
|
||||
return L10n.tr("Localizable", "seasonAndEpisode", String(describing: p1), String(describing: p2))
|
||||
}
|
||||
/// Seasons
|
||||
internal static let seasons = L10n.tr("Localizable", "seasons")
|
||||
/// See All
|
||||
internal static let seeAll = L10n.tr("Localizable", "seeAll")
|
||||
/// Select Cast Destination
|
||||
internal static let selectCastDestination = L10n.tr("Localizable", "selectCastDestination")
|
||||
/// Server Information
|
||||
internal static let serverInformation = L10n.tr("Localizable", "serverInformation")
|
||||
/// Server URL
|
||||
internal static let serverURL = L10n.tr("Localizable", "serverURL")
|
||||
/// Signed in as %@
|
||||
internal static func signedInAsWithString(_ p1: Any) -> String {
|
||||
return L10n.tr("Localizable", "signedInAsWithString", String(describing: p1))
|
||||
}
|
||||
/// Sort by
|
||||
internal static let sortBy = L10n.tr("Localizable", "sortBy")
|
||||
/// STUDIO
|
||||
internal static let studio = L10n.tr("Localizable", "studio")
|
||||
/// Studios
|
||||
internal static let studios = L10n.tr("Localizable", "studios")
|
||||
/// Suggestions
|
||||
internal static let suggestions = L10n.tr("Localizable", "suggestions")
|
||||
/// Switch user
|
||||
internal static let switchUser = L10n.tr("Localizable", "switchUser")
|
||||
/// System
|
||||
internal static let system = L10n.tr("Localizable", "system")
|
||||
/// Tags
|
||||
internal static let tags = L10n.tr("Localizable", "tags")
|
||||
/// Try again
|
||||
internal static let tryAgain = L10n.tr("Localizable", "tryAgain")
|
||||
/// Username
|
||||
internal static let username = L10n.tr("Localizable", "username")
|
||||
/// Who's watching?
|
||||
internal static let whosWatching = L10n.tr("Localizable", "WhosWatching")
|
||||
/// WIP
|
||||
internal static let wip = L10n.tr("Localizable", "wip")
|
||||
/// Your Favorites
|
||||
internal static let yourFavorites = L10n.tr("Localizable", "yourFavorites")
|
||||
}
|
||||
// swiftlint:enable explicit_type_interface function_parameter_count identifier_name line_length
|
||||
// swiftlint:enable nesting type_body_length type_name vertical_whitespace_opening_braces
|
||||
|
||||
// MARK: - Implementation Details
|
||||
|
||||
extension L10n {
|
||||
private static func tr(_ table: String, _ key: String, _ args: CVarArg...) -> String {
|
||||
let format = BundleToken.bundle.localizedString(forKey: key, value: nil, table: table)
|
||||
return String(format: format, locale: Locale.current, arguments: args)
|
||||
}
|
||||
}
|
||||
|
||||
// swiftlint:disable convenience_type
|
||||
private final class BundleToken {
|
||||
static let bundle: Bundle = {
|
||||
#if SWIFT_PACKAGE
|
||||
return Bundle.module
|
||||
#else
|
||||
return Bundle(for: BundleToken.self)
|
||||
#endif
|
||||
}()
|
||||
}
|
||||
// swiftlint:enable convenience_type
|
|
@ -16,7 +16,14 @@ enum AppAppearance: String, CaseIterable, Defaults.Serializable {
|
|||
case light
|
||||
|
||||
var localizedName: String {
|
||||
return NSLocalizedString(self.rawValue.capitalized, comment: "")
|
||||
switch self {
|
||||
case .system:
|
||||
return L10n.system
|
||||
case .dark:
|
||||
return L10n.dark
|
||||
case .light:
|
||||
return L10n.light
|
||||
}
|
||||
}
|
||||
|
||||
var style: UIUserInterfaceStyle {
|
||||
|
|
|
@ -22,7 +22,4 @@ struct DetailItem {
|
|||
let baseItem: BaseItemDto
|
||||
let type: DetailItemType
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -77,7 +77,7 @@ enum ItemType: String {
|
|||
var localized: String {
|
||||
switch self {
|
||||
case .episode:
|
||||
return "Episodes"
|
||||
return L10n.episodes
|
||||
case .movie:
|
||||
return "Movies"
|
||||
case .series:
|
||||
|
|
|
@ -35,7 +35,7 @@ class ItemViewModel: ViewModel {
|
|||
}
|
||||
|
||||
func playButtonText() -> String {
|
||||
return item.getItemProgressString() == "" ? "Play" : item.getItemProgressString()
|
||||
return item.getItemProgressString() == "" ? L10n.play : item.getItemProgressString()
|
||||
}
|
||||
|
||||
func getItemDisplayName() -> String {
|
||||
|
|
|
@ -64,7 +64,6 @@ final class LibraryViewModel: ViewModel {
|
|||
self.columns = columns
|
||||
super.init()
|
||||
|
||||
|
||||
$filters
|
||||
.sink(receiveValue: requestItems(with:))
|
||||
.store(in: &cancellables)
|
||||
|
|
|
@ -24,8 +24,8 @@ final class SeasonItemViewModel: ItemViewModel {
|
|||
}
|
||||
|
||||
override func playButtonText() -> String {
|
||||
guard let playButtonItem = playButtonItem else { return "Play" }
|
||||
guard let episodeLocator = playButtonItem.getEpisodeLocator() else { return "Play" }
|
||||
guard let playButtonItem = playButtonItem else { return L10n.play }
|
||||
guard let episodeLocator = playButtonItem.getEpisodeLocator() else { return L10n.play }
|
||||
return episodeLocator
|
||||
}
|
||||
|
||||
|
|
|
@ -23,8 +23,8 @@ final class SeriesItemViewModel: ItemViewModel {
|
|||
}
|
||||
|
||||
override func playButtonText() -> String {
|
||||
guard let playButtonItem = playButtonItem else { return "Play" }
|
||||
guard let episodeLocator = playButtonItem.getEpisodeLocator() else { return "Play" }
|
||||
guard let playButtonItem = playButtonItem else { return L10n.play }
|
||||
guard let episodeLocator = playButtonItem.getEpisodeLocator() else { return L10n.play }
|
||||
return episodeLocator
|
||||
}
|
||||
|
||||
|
|
|
@ -16,7 +16,7 @@ struct SearchBar: View {
|
|||
|
||||
var body: some View {
|
||||
HStack(spacing: 8) {
|
||||
TextField(NSLocalizedString("Search...", comment: ""), text: $text)
|
||||
TextField(L10n.search, text: $text)
|
||||
.padding(8)
|
||||
.padding(.horizontal, 16)
|
||||
#if os(iOS)
|
||||
|
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -24,7 +24,6 @@ struct NextUpWidgetProvider: TimelineProvider {
|
|||
}
|
||||
|
||||
func getSnapshot(in context: Context, completion: @escaping (NextUpEntry) -> Void) {
|
||||
|
||||
guard let currentLogin = SessionManager.main.currentLogin else { return }
|
||||
|
||||
let currentDate = Date()
|
||||
|
@ -68,7 +67,6 @@ struct NextUpWidgetProvider: TimelineProvider {
|
|||
}
|
||||
|
||||
func getTimeline(in context: Context, completion: @escaping (Timeline<Entry>) -> Void) {
|
||||
|
||||
guard let currentLogin = SessionManager.main.currentLogin else { return }
|
||||
|
||||
let currentDate = Date()
|
||||
|
@ -137,7 +135,7 @@ struct NextUpEntryView: View {
|
|||
}
|
||||
.background(Color.blue)
|
||||
} else if entry.items.isEmpty {
|
||||
Text("Empty Next Up")
|
||||
L10n.emptyNextUp.text
|
||||
.font(.body)
|
||||
.bold()
|
||||
.foregroundColor(.primary)
|
||||
|
@ -216,7 +214,7 @@ extension NextUpEntryView {
|
|||
.fontWeight(.semibold)
|
||||
.foregroundColor(.primary)
|
||||
.lineLimit(1)
|
||||
Text("\(item.0.name ?? "") · S\(item.0.parentIndexNumber ?? 0):E\(item.0.indexNumber ?? 0)")
|
||||
Text("\(item.0.name ?? "") · \(L10n.seasonAndEpisode(String(item.0.parentIndexNumber ?? 0), String(item.0.indexNumber ?? 0)))")
|
||||
.font(.caption)
|
||||
.fontWeight(.semibold)
|
||||
.foregroundColor(.secondary)
|
||||
|
@ -243,7 +241,8 @@ extension NextUpEntryView {
|
|||
.fontWeight(.semibold)
|
||||
.foregroundColor(.primary)
|
||||
.frame(minWidth: 0, maxWidth: .infinity, alignment: .leading)
|
||||
Text("\(item.0.name ?? "") · S\(item.0.parentIndexNumber ?? 0):E\(item.0.indexNumber ?? 0)")
|
||||
|
||||
Text("\(item.0.name ?? "") · \(L10n.seasonAndEpisode(String(item.0.parentIndexNumber ?? 0), String(item.0.indexNumber ?? 0)))")
|
||||
.font(.caption)
|
||||
.fontWeight(.semibold)
|
||||
.foregroundColor(.secondary)
|
||||
|
@ -305,7 +304,7 @@ extension NextUpEntryView {
|
|||
.fontWeight(.semibold)
|
||||
.foregroundColor(.white)
|
||||
.frame(minWidth: 0, maxWidth: .infinity, alignment: .leading)
|
||||
Text("\(firstItem.0.name ?? "") · S\(firstItem.0.parentIndexNumber ?? 0):E\(firstItem.0.indexNumber ?? 0)")
|
||||
Text("\(firstItem.0.name ?? "") · \(L10n.seasonAndEpisode(String(firstItem.0.parentIndexNumber ?? 0), String(firstItem.0.indexNumber ?? 0)))")
|
||||
.font(.caption)
|
||||
.fontWeight(.semibold)
|
||||
.foregroundColor(.gray)
|
||||
|
@ -347,7 +346,7 @@ struct NextUpWidget: Widget {
|
|||
provider: NextUpWidgetProvider()) { entry in
|
||||
NextUpEntryView(entry: entry)
|
||||
}
|
||||
.configurationDisplayName("Next Up")
|
||||
.configurationDisplayName(L10n.nextUp)
|
||||
.description("Keep watching where you left off or see what's up next.")
|
||||
.supportedFamilies([.systemSmall, .systemMedium, .systemLarge])
|
||||
}
|
||||
|
@ -366,7 +365,7 @@ struct NextUpWidget_Previews: PreviewProvider {
|
|||
(.init(name: "Name0", indexNumber: 10, parentIndexNumber: 0, seriesName: "Series0"),
|
||||
UIImage(named: "WidgetHeaderSymbol")),
|
||||
(.init(name: "Name1", indexNumber: 10, parentIndexNumber: 0, seriesName: "Series1"),
|
||||
UIImage(named: "WidgetHeaderSymbol")),
|
||||
UIImage(named: "WidgetHeaderSymbol"))
|
||||
],
|
||||
error: nil))
|
||||
.previewContext(WidgetPreviewContext(family: .systemMedium))
|
||||
|
@ -377,7 +376,7 @@ struct NextUpWidget_Previews: PreviewProvider {
|
|||
(.init(name: "Name1", indexNumber: 10, parentIndexNumber: 0, seriesName: "Series1"),
|
||||
UIImage(named: "WidgetHeaderSymbol")),
|
||||
(.init(name: "Name2", indexNumber: 10, parentIndexNumber: 0, seriesName: "Series2"),
|
||||
UIImage(named: "WidgetHeaderSymbol")),
|
||||
UIImage(named: "WidgetHeaderSymbol"))
|
||||
],
|
||||
error: nil))
|
||||
.previewContext(WidgetPreviewContext(family: .systemLarge))
|
||||
|
@ -392,7 +391,7 @@ struct NextUpWidget_Previews: PreviewProvider {
|
|||
(.init(name: "Name0", indexNumber: 10, parentIndexNumber: 0, seriesName: "Series0"),
|
||||
UIImage(named: "WidgetHeaderSymbol")),
|
||||
(.init(name: "Name1", indexNumber: 10, parentIndexNumber: 0, seriesName: "Series1"),
|
||||
UIImage(named: "WidgetHeaderSymbol")),
|
||||
UIImage(named: "WidgetHeaderSymbol"))
|
||||
],
|
||||
error: nil))
|
||||
.previewContext(WidgetPreviewContext(family: .systemMedium))
|
||||
|
@ -404,7 +403,7 @@ struct NextUpWidget_Previews: PreviewProvider {
|
|||
(.init(name: "Name1", indexNumber: 10, parentIndexNumber: 0, seriesName: "Series1"),
|
||||
UIImage(named: "WidgetHeaderSymbol")),
|
||||
(.init(name: "Name2", indexNumber: 10, parentIndexNumber: 0, seriesName: "Series2"),
|
||||
UIImage(named: "WidgetHeaderSymbol")),
|
||||
UIImage(named: "WidgetHeaderSymbol"))
|
||||
],
|
||||
error: nil))
|
||||
.previewContext(WidgetPreviewContext(family: .systemLarge))
|
||||
|
@ -417,7 +416,7 @@ struct NextUpWidget_Previews: PreviewProvider {
|
|||
NextUpEntryView(entry: .init(date: Date(),
|
||||
items: [
|
||||
(.init(name: "Name0", indexNumber: 10, parentIndexNumber: 0, seriesName: "Series0"),
|
||||
UIImage(named: "WidgetHeaderSymbol")),
|
||||
UIImage(named: "WidgetHeaderSymbol"))
|
||||
],
|
||||
error: nil))
|
||||
.previewContext(WidgetPreviewContext(family: .systemMedium))
|
||||
|
@ -427,7 +426,7 @@ struct NextUpWidget_Previews: PreviewProvider {
|
|||
(.init(name: "Name0", indexNumber: 10, parentIndexNumber: 0, seriesName: "Series0"),
|
||||
UIImage(named: "WidgetHeaderSymbol")),
|
||||
(.init(name: "Name1", indexNumber: 10, parentIndexNumber: 0, seriesName: "Series1"),
|
||||
UIImage(named: "WidgetHeaderSymbol")),
|
||||
UIImage(named: "WidgetHeaderSymbol"))
|
||||
],
|
||||
error: nil))
|
||||
.previewContext(WidgetPreviewContext(family: .systemLarge))
|
||||
|
|
|
@ -0,0 +1,42 @@
|
|||
<?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>BuildMachineOSBuild</key>
|
||||
<string></string>
|
||||
<key>CFBundleDevelopmentRegion</key>
|
||||
<string>en</string>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>SwiftGen_SwiftGenCLI</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>SwiftGen.SwiftGenCLI.resources</string>
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
<string>6.0</string>
|
||||
<key>CFBundleName</key>
|
||||
<string>SwiftGen_SwiftGenCLI</string>
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>BNDL</string>
|
||||
<key>CFBundleSupportedPlatforms</key>
|
||||
<array>
|
||||
<string>MacOSX</string>
|
||||
</array>
|
||||
<key>DTCompiler</key>
|
||||
<string>com.apple.compilers.llvm.clang.1_0</string>
|
||||
<key>DTPlatformBuild</key>
|
||||
<string>13A233</string>
|
||||
<key>DTPlatformName</key>
|
||||
<string>macosx</string>
|
||||
<key>DTPlatformVersion</key>
|
||||
<string>11.3</string>
|
||||
<key>DTSDKBuild</key>
|
||||
<string>20E214</string>
|
||||
<key>DTSDKName</key>
|
||||
<string>macosx11.3</string>
|
||||
<key>DTXcode</key>
|
||||
<string>1300</string>
|
||||
<key>DTXcodeBuild</key>
|
||||
<string>13A233</string>
|
||||
<key>LSMinimumSystemVersion</key>
|
||||
<string>10.11</string>
|
||||
</dict>
|
||||
</plist>
|
|
@ -0,0 +1,43 @@
|
|||
// swiftlint:disable all
|
||||
// Generated using SwiftGen — https://github.com/SwiftGen/SwiftGen
|
||||
|
||||
{% if palettes %}
|
||||
{% set enumName %}{{param.enumName|default:"ColorName"}}{% endset %}
|
||||
{% set accessModifier %}{% if param.publicAccess %}public{% else %}internal{% endif %}{% endset %}
|
||||
#if os(macOS)
|
||||
import AppKit
|
||||
{% if enumName != 'NSColor' %}{{accessModifier}} enum {{enumName}} { }{% endif %}
|
||||
#elseif os(iOS) || os(tvOS) || os(watchOS)
|
||||
import UIKit
|
||||
{% if enumName != 'UIColor' %}{{accessModifier}} enum {{enumName}} { }{% endif %}
|
||||
#endif
|
||||
|
||||
// swiftlint:disable superfluous_disable_command
|
||||
// swiftlint:disable file_length
|
||||
|
||||
// MARK: - Colors
|
||||
|
||||
// swiftlint:disable identifier_name line_length type_body_length
|
||||
{{accessModifier}} extension {{enumName}} {
|
||||
{% macro h2f hex %}{{hex|hexToInt|int255toFloat}}{% endmacro %}
|
||||
{% macro enumBlock colors accessPrefix %}
|
||||
{% for color in colors %}
|
||||
/// 0x{{color.red}}{{color.green}}{{color.blue}}{{color.alpha}} (r: {{color.red|hexToInt}}, g: {{color.green|hexToInt}}, b: {{color.blue|hexToInt}}, a: {{color.alpha|hexToInt}})
|
||||
{{accessPrefix}}static let {{color.name|swiftIdentifier:"pretty"|lowerFirstWord|escapeReservedKeywords}} = #colorLiteral(red: {% call h2f color.red %}, green: {% call h2f color.green %}, blue: {% call h2f color.blue %}, alpha: {% call h2f color.alpha %})
|
||||
{% endfor %}
|
||||
{% endmacro %}
|
||||
{% if palettes.count > 1 or param.forceFileNameEnum %}
|
||||
{% set accessPrefix %}{{accessModifier}} {% endset %}
|
||||
{% for palette in palettes %}
|
||||
enum {{palette.name|swiftIdentifier:"pretty"|escapeReservedKeywords}} {
|
||||
{% filter indent:2 %}{% call enumBlock palette.colors accessPrefix %}{% endfilter %}
|
||||
}
|
||||
{% endfor %}
|
||||
{% else %}
|
||||
{% call enumBlock palettes.first.colors "" %}
|
||||
{% endif %}
|
||||
}
|
||||
// swiftlint:enable identifier_name line_length type_body_length
|
||||
{% else %}
|
||||
// No color found
|
||||
{% endif %}
|
|
@ -0,0 +1,43 @@
|
|||
// swiftlint:disable all
|
||||
// Generated using SwiftGen — https://github.com/SwiftGen/SwiftGen
|
||||
|
||||
{% if palettes %}
|
||||
{% set enumName %}{{param.enumName|default:"ColorName"}}{% endset %}
|
||||
{% set accessModifier %}{% if param.publicAccess %}public{% else %}internal{% endif %}{% endset %}
|
||||
#if os(macOS)
|
||||
import AppKit
|
||||
{% if enumName != 'NSColor' %}{{accessModifier}} enum {{enumName}} { }{% endif %}
|
||||
#elseif os(iOS) || os(tvOS) || os(watchOS)
|
||||
import UIKit
|
||||
{% if enumName != 'UIColor' %}{{accessModifier}} enum {{enumName}} { }{% endif %}
|
||||
#endif
|
||||
|
||||
// swiftlint:disable superfluous_disable_command
|
||||
// swiftlint:disable file_length
|
||||
|
||||
// MARK: - Colors
|
||||
|
||||
// swiftlint:disable identifier_name line_length type_body_length
|
||||
{{accessModifier}} extension {{enumName}} {
|
||||
{% macro h2f hex %}{{hex|hexToInt|int255toFloat}}{% endmacro %}
|
||||
{% macro enumBlock colors accessPrefix %}
|
||||
{% for color in colors %}
|
||||
/// 0x{{color.red}}{{color.green}}{{color.blue}}{{color.alpha}} (r: {{color.red|hexToInt}}, g: {{color.green|hexToInt}}, b: {{color.blue|hexToInt}}, a: {{color.alpha|hexToInt}})
|
||||
{{accessPrefix}}static let {{color.name|swiftIdentifier:"pretty"|lowerFirstWord|escapeReservedKeywords}} = #colorLiteral(red: {% call h2f color.red %}, green: {% call h2f color.green %}, blue: {% call h2f color.blue %}, alpha: {% call h2f color.alpha %})
|
||||
{% endfor %}
|
||||
{% endmacro %}
|
||||
{% if palettes.count > 1 or param.forceFileNameEnum %}
|
||||
{% set accessPrefix %}{{accessModifier}} {% endset %}
|
||||
{% for palette in palettes %}
|
||||
enum {{palette.name|swiftIdentifier:"pretty"|escapeReservedKeywords}} {
|
||||
{% filter indent:2 %}{% call enumBlock palette.colors accessPrefix %}{% endfilter %}
|
||||
}
|
||||
{% endfor %}
|
||||
{% else %}
|
||||
{% call enumBlock palettes.first.colors "" %}
|
||||
{% endif %}
|
||||
}
|
||||
// swiftlint:enable identifier_name line_length type_body_length
|
||||
{% else %}
|
||||
// No color found
|
||||
{% endif %}
|
|
@ -0,0 +1,84 @@
|
|||
// swiftlint:disable all
|
||||
// Generated using SwiftGen — https://github.com/SwiftGen/SwiftGen
|
||||
|
||||
{% if palettes %}
|
||||
{% set colorAlias %}{{param.colorAliasName|default:"Color"}}{% endset %}
|
||||
{% set accessModifier %}{% if param.publicAccess %}public{% else %}internal{% endif %}{% endset %}
|
||||
#if os(macOS)
|
||||
import AppKit.NSColor
|
||||
{{accessModifier}} typealias {{colorAlias}} = NSColor
|
||||
#elseif os(iOS) || os(tvOS) || os(watchOS)
|
||||
import UIKit.UIColor
|
||||
{{accessModifier}} typealias {{colorAlias}} = UIColor
|
||||
#endif
|
||||
|
||||
// swiftlint:disable superfluous_disable_command file_length implicit_return
|
||||
|
||||
// MARK: - Colors
|
||||
|
||||
// swiftlint:disable identifier_name line_length type_body_length
|
||||
{% set enumName %}{{param.enumName|default:"ColorName"}}{% endset %}
|
||||
{{accessModifier}} struct {{enumName}} {
|
||||
{{accessModifier}} let rgbaValue: UInt32
|
||||
{{accessModifier}} var color: {{colorAlias}} { return {{colorAlias}}(named: self) }
|
||||
|
||||
{% macro rgbaValue color %}0x{{color.red}}{{color.green}}{{color.blue}}{{color.alpha}}{% endmacro %}
|
||||
{% macro enumBlock colors %}
|
||||
{% for color in colors %}
|
||||
/// <span style="display:block;width:3em;height:2em;border:1px solid black;background:#{{color.red}}{{color.green}}{{color.blue}}"></span>
|
||||
/// Alpha: {{color.alpha|hexToInt|int255toFloat|percent}} <br/> (0x{{color.red}}{{color.green}}{{color.blue}}{{color.alpha}})
|
||||
{{accessModifier}} static let {{color.name|swiftIdentifier:"pretty"|lowerFirstWord|escapeReservedKeywords}} = {{enumName}}(rgbaValue: {% call rgbaValue color %})
|
||||
{% endfor %}
|
||||
{% endmacro %}
|
||||
{% if palettes.count > 1 or param.forceFileNameEnum %}
|
||||
{% for palette in palettes %}
|
||||
{{accessModifier}} enum {{palette.name|swiftIdentifier:"pretty"|escapeReservedKeywords}} {
|
||||
{% filter indent:2 %}{% call enumBlock palette.colors %}{% endfilter %}
|
||||
}
|
||||
{% endfor %}
|
||||
{% else %}
|
||||
{% call enumBlock palettes.first.colors %}
|
||||
{% endif %}
|
||||
}
|
||||
// swiftlint:enable identifier_name line_length type_body_length
|
||||
|
||||
// MARK: - Implementation Details
|
||||
|
||||
internal extension {{colorAlias}} {
|
||||
convenience init(rgbaValue: UInt32) {
|
||||
let components = RGBAComponents(rgbaValue: rgbaValue).normalized
|
||||
self.init(red: components[0], green: components[1], blue: components[2], alpha: components[3])
|
||||
}
|
||||
}
|
||||
|
||||
private struct RGBAComponents {
|
||||
let rgbaValue: UInt32
|
||||
|
||||
private var shifts: [UInt32] {
|
||||
[
|
||||
rgbaValue >> 24, // red
|
||||
rgbaValue >> 16, // green
|
||||
rgbaValue >> 8, // blue
|
||||
rgbaValue // alpha
|
||||
]
|
||||
}
|
||||
|
||||
private var components: [CGFloat] {
|
||||
shifts.map {
|
||||
CGFloat($0 & 0xff)
|
||||
}
|
||||
}
|
||||
|
||||
var normalized: [CGFloat] {
|
||||
components.map { $0 / 255.0 }
|
||||
}
|
||||
}
|
||||
|
||||
{{accessModifier}} extension {{colorAlias}} {
|
||||
convenience init(named color: {{enumName}}) {
|
||||
self.init(rgbaValue: color.rgbaValue)
|
||||
}
|
||||
}
|
||||
{% else %}
|
||||
// No color found
|
||||
{% endif %}
|
|
@ -0,0 +1,84 @@
|
|||
// swiftlint:disable all
|
||||
// Generated using SwiftGen — https://github.com/SwiftGen/SwiftGen
|
||||
|
||||
{% if palettes %}
|
||||
{% set colorAlias %}{{param.colorAliasName|default:"Color"}}{% endset %}
|
||||
{% set accessModifier %}{% if param.publicAccess %}public{% else %}internal{% endif %}{% endset %}
|
||||
#if os(macOS)
|
||||
import AppKit.NSColor
|
||||
{{accessModifier}} typealias {{colorAlias}} = NSColor
|
||||
#elseif os(iOS) || os(tvOS) || os(watchOS)
|
||||
import UIKit.UIColor
|
||||
{{accessModifier}} typealias {{colorAlias}} = UIColor
|
||||
#endif
|
||||
|
||||
// swiftlint:disable superfluous_disable_command file_length implicit_return
|
||||
|
||||
// MARK: - Colors
|
||||
|
||||
// swiftlint:disable identifier_name line_length type_body_length
|
||||
{% set enumName %}{{param.enumName|default:"ColorName"}}{% endset %}
|
||||
{{accessModifier}} struct {{enumName}} {
|
||||
{{accessModifier}} let rgbaValue: UInt32
|
||||
{{accessModifier}} var color: {{colorAlias}} { return {{colorAlias}}(named: self) }
|
||||
|
||||
{% macro rgbaValue color %}0x{{color.red}}{{color.green}}{{color.blue}}{{color.alpha}}{% endmacro %}
|
||||
{% macro enumBlock colors %}
|
||||
{% for color in colors %}
|
||||
/// <span style="display:block;width:3em;height:2em;border:1px solid black;background:#{{color.red}}{{color.green}}{{color.blue}}"></span>
|
||||
/// Alpha: {{color.alpha|hexToInt|int255toFloat|percent}} <br/> (0x{{color.red}}{{color.green}}{{color.blue}}{{color.alpha}})
|
||||
{{accessModifier}} static let {{color.name|swiftIdentifier:"pretty"|lowerFirstWord|escapeReservedKeywords}} = {{enumName}}(rgbaValue: {% call rgbaValue color %})
|
||||
{% endfor %}
|
||||
{% endmacro %}
|
||||
{% if palettes.count > 1 or param.forceFileNameEnum %}
|
||||
{% for palette in palettes %}
|
||||
{{accessModifier}} enum {{palette.name|swiftIdentifier:"pretty"|escapeReservedKeywords}} {
|
||||
{% filter indent:2 %}{% call enumBlock palette.colors %}{% endfilter %}
|
||||
}
|
||||
{% endfor %}
|
||||
{% else %}
|
||||
{% call enumBlock palettes.first.colors %}
|
||||
{% endif %}
|
||||
}
|
||||
// swiftlint:enable identifier_name line_length type_body_length
|
||||
|
||||
// MARK: - Implementation Details
|
||||
|
||||
internal extension {{colorAlias}} {
|
||||
convenience init(rgbaValue: UInt32) {
|
||||
let components = RGBAComponents(rgbaValue: rgbaValue).normalized
|
||||
self.init(red: components[0], green: components[1], blue: components[2], alpha: components[3])
|
||||
}
|
||||
}
|
||||
|
||||
private struct RGBAComponents {
|
||||
let rgbaValue: UInt32
|
||||
|
||||
private var shifts: [UInt32] {
|
||||
[
|
||||
rgbaValue >> 24, // red
|
||||
rgbaValue >> 16, // green
|
||||
rgbaValue >> 8, // blue
|
||||
rgbaValue // alpha
|
||||
]
|
||||
}
|
||||
|
||||
private var components: [CGFloat] {
|
||||
shifts.map {
|
||||
CGFloat($0 & 0xff)
|
||||
}
|
||||
}
|
||||
|
||||
var normalized: [CGFloat] {
|
||||
components.map { $0 / 255.0 }
|
||||
}
|
||||
}
|
||||
|
||||
{{accessModifier}} extension {{colorAlias}} {
|
||||
convenience init(named color: {{enumName}}) {
|
||||
self.init(rgbaValue: color.rgbaValue)
|
||||
}
|
||||
}
|
||||
{% else %}
|
||||
// No color found
|
||||
{% endif %}
|
|
@ -0,0 +1,211 @@
|
|||
// swiftlint:disable all
|
||||
// Generated using SwiftGen — https://github.com/SwiftGen/SwiftGen
|
||||
|
||||
// swiftlint:disable superfluous_disable_command implicit_return
|
||||
// swiftlint:disable sorted_imports
|
||||
import CoreData
|
||||
import Foundation
|
||||
{% for import in param.extraImports %}
|
||||
import {{ import }}
|
||||
{% empty %}
|
||||
{# If extraImports is a single String instead of an array, `for` considers it empty but we still have to check if there's a single String value #}
|
||||
{% if param.extraImports %}import {{ param.extraImports }}{% endif %}
|
||||
{% endfor %}
|
||||
|
||||
// swiftlint:disable attributes file_length vertical_whitespace_closing_braces
|
||||
// swiftlint:disable identifier_name line_length type_body_length
|
||||
{% set accessModifier %}{% if param.publicAccess %}public{% else %}internal{% endif %}{% endset %}
|
||||
|
||||
{% for model in models %}
|
||||
{% for name, entity in model.entities %}
|
||||
{% set superclass %}{{ model.entities[entity.superEntity].className|default:"NSManagedObject" }}{% endset %}
|
||||
{% set entityClassName %}{{ entity.className|default:"NSManagedObject" }}{% endset %}
|
||||
// MARK: - {{ entity.name }}
|
||||
|
||||
{% if not entity.shouldGenerateCode %}
|
||||
// Note: '{{ entity.name }}' has codegen enabled for Xcode, skipping code generation.
|
||||
|
||||
{% elif entityClassName|contains:"." %}
|
||||
// Warning: '{{ entityClassName }}' cannot be a valid type name, skipping code generation.
|
||||
|
||||
{% else %}
|
||||
{% if param.generateObjcName %}
|
||||
@objc({{ entityClassName }})
|
||||
{% endif %}
|
||||
{{ accessModifier }} class {{ entityClassName }}: {{ superclass }} {
|
||||
{% set override %}{% if superclass != "NSManagedObject" %}override {% endif %}{% endset %}
|
||||
{{ override }}{{ accessModifier }} class var entityName: String {
|
||||
return "{{ entity.name }}"
|
||||
}
|
||||
|
||||
{{ override }}{{ accessModifier }} class func entity(in managedObjectContext: NSManagedObjectContext) -> NSEntityDescription? {
|
||||
return NSEntityDescription.entity(forEntityName: entityName, in: managedObjectContext)
|
||||
}
|
||||
|
||||
@available(*, deprecated, renamed: "makeFetchRequest", message: "To avoid collisions with the less concrete method in `NSManagedObject`, please use `makeFetchRequest()` instead.")
|
||||
@nonobjc {{ accessModifier }} class func fetchRequest() -> NSFetchRequest<{{ entityClassName }}> {
|
||||
return NSFetchRequest<{{ entityClassName }}>(entityName: entityName)
|
||||
}
|
||||
|
||||
@nonobjc {{ accessModifier }} class func makeFetchRequest() -> NSFetchRequest<{{ entityClassName }}> {
|
||||
return NSFetchRequest<{{ entityClassName }}>(entityName: entityName)
|
||||
}
|
||||
|
||||
// swiftlint:disable discouraged_optional_boolean discouraged_optional_collection
|
||||
{% for attribute in entity.attributes %}
|
||||
{% if attribute.userInfo.RawType %}
|
||||
{% set rawType attribute.userInfo.RawType %}
|
||||
{% set unwrapOptional attribute.userInfo.unwrapOptional %}
|
||||
{{ accessModifier }} var {{ attribute.name }}: {{ rawType }}{% if not unwrapOptional %}?{% endif %} {
|
||||
get {
|
||||
let key = "{{ attribute.name }}"
|
||||
willAccessValue(forKey: key)
|
||||
defer { didAccessValue(forKey: key) }
|
||||
|
||||
{% if unwrapOptional %}
|
||||
guard let value = primitiveValue(forKey: key) as? {{ rawType }}.RawValue,
|
||||
let result = {{ rawType }}(rawValue: value) else {
|
||||
fatalError("Could not convert value for key '\(key)' to type '{{ rawType }}'")
|
||||
}
|
||||
return result
|
||||
{% else %}
|
||||
guard let value = primitiveValue(forKey: key) as? {{ rawType }}.RawValue else {
|
||||
return nil
|
||||
}
|
||||
return {{ rawType }}(rawValue: value)
|
||||
{% endif %}
|
||||
}
|
||||
set {
|
||||
let key = "{{ attribute.name }}"
|
||||
willChangeValue(forKey: key)
|
||||
defer { didChangeValue(forKey: key) }
|
||||
|
||||
setPrimitiveValue(newValue{% if not unwrapOptional %}?{% endif %}.rawValue, forKey: key)
|
||||
}
|
||||
}
|
||||
{% elif attribute.usesScalarValueType and attribute.isOptional %}
|
||||
{{ accessModifier }} var {{ attribute.name }}: {{ attribute.typeName }}? {
|
||||
get {
|
||||
let key = "{{ attribute.name }}"
|
||||
willAccessValue(forKey: key)
|
||||
defer { didAccessValue(forKey: key) }
|
||||
|
||||
return primitiveValue(forKey: key) as? {{ attribute.typeName }}
|
||||
}
|
||||
set {
|
||||
let key = "{{ attribute.name }}"
|
||||
willChangeValue(forKey: key)
|
||||
defer { didChangeValue(forKey: key) }
|
||||
|
||||
setPrimitiveValue(newValue, forKey: key)
|
||||
}
|
||||
}
|
||||
{% else %}
|
||||
@NSManaged {{ accessModifier }} var {{ attribute.name }}: {{ attribute.typeName }}{% if attribute.isOptional %}?{% endif %}
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
{% for relationship in entity.relationships %}
|
||||
{% if relationship.isToMany %}
|
||||
@NSManaged {{ accessModifier }} var {{ relationship.name }}: {% if relationship.isOrdered %}NSOrderedSet{% else %}Set<{{ model.entities[relationship.destinationEntity].className|default:"NSManagedObject" }}>{% endif %}{% if relationship.isOptional %}?{% endif %}
|
||||
{% else %}
|
||||
@NSManaged {{ accessModifier }} var {{ relationship.name }}: {{ model.entities[relationship.destinationEntity].className|default:"NSManagedObject" }}{% if relationship.isOptional %}?{% endif %}
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
{% for fetchedProperty in entity.fetchedProperties %}
|
||||
@NSManaged {{ accessModifier }} var {{ fetchedProperty.name }}: [{{ fetchedProperty.fetchRequest.entity }}]
|
||||
{% endfor %}
|
||||
// swiftlint:enable discouraged_optional_boolean discouraged_optional_collection
|
||||
}
|
||||
|
||||
{% for relationship in entity.relationships where relationship.isToMany %}
|
||||
{% set destinationEntityClassName %}{{ model.entities[relationship.destinationEntity].className|default:"NSManagedObject" }}{% endset %}
|
||||
{% set collectionClassName %}{% if relationship.isOrdered %}NSOrderedSet{% else %}Set<{{ destinationEntityClassName }}>{% endif %}{% endset %}
|
||||
{% set relationshipName %}{{ relationship.name | upperFirstLetter }}{% endset %}
|
||||
// MARK: Relationship {{ relationshipName }}
|
||||
|
||||
extension {{ entityClassName }} {
|
||||
{% if relationship.isOrdered %}
|
||||
@objc(insertObject:in{{ relationshipName }}AtIndex:)
|
||||
@NSManaged public func insertInto{{ relationshipName }}(_ value: {{ destinationEntityClassName }}, at idx: Int)
|
||||
|
||||
@objc(removeObjectFrom{{ relationshipName }}AtIndex:)
|
||||
@NSManaged public func removeFrom{{ relationshipName }}(at idx: Int)
|
||||
|
||||
@objc(insert{{ relationshipName }}:atIndexes:)
|
||||
@NSManaged public func insertInto{{ relationshipName }}(_ values: [{{ destinationEntityClassName }}], at indexes: NSIndexSet)
|
||||
|
||||
@objc(remove{{ relationshipName }}AtIndexes:)
|
||||
@NSManaged public func removeFrom{{ relationshipName }}(at indexes: NSIndexSet)
|
||||
|
||||
@objc(replaceObjectIn{{ relationshipName }}AtIndex:withObject:)
|
||||
@NSManaged public func replace{{ relationshipName }}(at idx: Int, with value: {{ destinationEntityClassName }})
|
||||
|
||||
@objc(replace{{ relationshipName }}AtIndexes:with{{ relationshipName }}:)
|
||||
@NSManaged public func replace{{ relationshipName }}(at indexes: NSIndexSet, with values: [{{ destinationEntityClassName }}])
|
||||
|
||||
{% endif %}
|
||||
@objc(add{{ relationshipName }}Object:)
|
||||
@NSManaged public func addTo{{ relationshipName }}(_ value: {{ destinationEntityClassName }})
|
||||
|
||||
@objc(remove{{ relationshipName }}Object:)
|
||||
@NSManaged public func removeFrom{{ relationshipName }}(_ value: {{ destinationEntityClassName }})
|
||||
|
||||
@objc(add{{ relationshipName }}:)
|
||||
@NSManaged public func addTo{{ relationshipName }}(_ values: {{ collectionClassName }})
|
||||
|
||||
@objc(remove{{ relationshipName }}:)
|
||||
@NSManaged public func removeFrom{{ relationshipName }}(_ values: {{ collectionClassName }})
|
||||
}
|
||||
|
||||
{% endfor %}
|
||||
{% if model.fetchRequests[entity.name].count > 0 %}
|
||||
// MARK: Fetch Requests
|
||||
|
||||
extension {{ entityClassName }} {
|
||||
{% for fetchRequest in model.fetchRequests[entity.name] %}
|
||||
{% set resultTypeName %}{% filter removeNewlines:"leading" %}
|
||||
{% if fetchRequest.resultType == "Object" %}
|
||||
{{ entityClassName }}
|
||||
{% elif fetchRequest.resultType == "Object ID" %}
|
||||
NSManagedObjectID
|
||||
{% elif fetchRequest.resultType == "Dictionary" %}
|
||||
[String: Any]
|
||||
{% endif %}
|
||||
{% endfilter %}{% endset %}
|
||||
class func fetch{{ fetchRequest.name | upperFirstLetter }}({% filter removeNewlines:"leading" %}
|
||||
managedObjectContext: NSManagedObjectContext
|
||||
{% for variableName, variableType in fetchRequest.substitutionVariables %}
|
||||
, {{ variableName | lowerFirstWord }}: {{ variableType }}
|
||||
{% endfor %}
|
||||
{% endfilter %}) throws -> [{{ resultTypeName }}] {
|
||||
guard let persistentStoreCoordinator = managedObjectContext.persistentStoreCoordinator else {
|
||||
fatalError("Managed object context has no persistent store coordinator for getting fetch request templates")
|
||||
}
|
||||
let model = persistentStoreCoordinator.managedObjectModel
|
||||
let substitutionVariables: [String: Any] = [
|
||||
{% for variableName, variableType in fetchRequest.substitutionVariables %}
|
||||
"{{ variableName }}": {{ variableName | lowerFirstWord }}{{ "," if not forloop.last }}
|
||||
{% empty %}
|
||||
:
|
||||
{% endfor %}
|
||||
]
|
||||
|
||||
guard let fetchRequest = model.fetchRequestFromTemplate(withName: "{{ fetchRequest.name }}", substitutionVariables: substitutionVariables) else {
|
||||
fatalError("No fetch request template named '{{ fetchRequest.name }}' found.")
|
||||
}
|
||||
|
||||
guard let result = try managedObjectContext.fetch(fetchRequest) as? [{{ resultTypeName }}] else {
|
||||
fatalError("Unable to cast fetch result to correct result type.")
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
{% endfor %}
|
||||
}
|
||||
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
{% endfor %}
|
||||
// swiftlint:enable identifier_name line_length type_body_length
|
|
@ -0,0 +1,211 @@
|
|||
// swiftlint:disable all
|
||||
// Generated using SwiftGen — https://github.com/SwiftGen/SwiftGen
|
||||
|
||||
// swiftlint:disable superfluous_disable_command implicit_return
|
||||
// swiftlint:disable sorted_imports
|
||||
import CoreData
|
||||
import Foundation
|
||||
{% for import in param.extraImports %}
|
||||
import {{ import }}
|
||||
{% empty %}
|
||||
{# If extraImports is a single String instead of an array, `for` considers it empty but we still have to check if there's a single String value #}
|
||||
{% if param.extraImports %}import {{ param.extraImports }}{% endif %}
|
||||
{% endfor %}
|
||||
|
||||
// swiftlint:disable attributes file_length vertical_whitespace_closing_braces
|
||||
// swiftlint:disable identifier_name line_length type_body_length
|
||||
{% set accessModifier %}{% if param.publicAccess %}public{% else %}internal{% endif %}{% endset %}
|
||||
|
||||
{% for model in models %}
|
||||
{% for name, entity in model.entities %}
|
||||
{% set superclass %}{{ model.entities[entity.superEntity].className|default:"NSManagedObject" }}{% endset %}
|
||||
{% set entityClassName %}{{ entity.className|default:"NSManagedObject" }}{% endset %}
|
||||
// MARK: - {{ entity.name }}
|
||||
|
||||
{% if not entity.shouldGenerateCode %}
|
||||
// Note: '{{ entity.name }}' has codegen enabled for Xcode, skipping code generation.
|
||||
|
||||
{% elif entityClassName|contains:"." %}
|
||||
// Warning: '{{ entityClassName }}' cannot be a valid type name, skipping code generation.
|
||||
|
||||
{% else %}
|
||||
{% if param.generateObjcName %}
|
||||
@objc({{ entityClassName }})
|
||||
{% endif %}
|
||||
{{ accessModifier }} class {{ entityClassName }}: {{ superclass }} {
|
||||
{% set override %}{% if superclass != "NSManagedObject" %}override {% endif %}{% endset %}
|
||||
{{ override }}{{ accessModifier }} class var entityName: String {
|
||||
return "{{ entity.name }}"
|
||||
}
|
||||
|
||||
{{ override }}{{ accessModifier }} class func entity(in managedObjectContext: NSManagedObjectContext) -> NSEntityDescription? {
|
||||
return NSEntityDescription.entity(forEntityName: entityName, in: managedObjectContext)
|
||||
}
|
||||
|
||||
@available(*, deprecated, renamed: "makeFetchRequest", message: "To avoid collisions with the less concrete method in `NSManagedObject`, please use `makeFetchRequest()` instead.")
|
||||
@nonobjc {{ accessModifier }} class func fetchRequest() -> NSFetchRequest<{{ entityClassName }}> {
|
||||
return NSFetchRequest<{{ entityClassName }}>(entityName: entityName)
|
||||
}
|
||||
|
||||
@nonobjc {{ accessModifier }} class func makeFetchRequest() -> NSFetchRequest<{{ entityClassName }}> {
|
||||
return NSFetchRequest<{{ entityClassName }}>(entityName: entityName)
|
||||
}
|
||||
|
||||
// swiftlint:disable discouraged_optional_boolean discouraged_optional_collection
|
||||
{% for attribute in entity.attributes %}
|
||||
{% if attribute.userInfo.RawType %}
|
||||
{% set rawType attribute.userInfo.RawType %}
|
||||
{% set unwrapOptional attribute.userInfo.unwrapOptional %}
|
||||
{{ accessModifier }} var {{ attribute.name }}: {{ rawType }}{% if not unwrapOptional %}?{% endif %} {
|
||||
get {
|
||||
let key = "{{ attribute.name }}"
|
||||
willAccessValue(forKey: key)
|
||||
defer { didAccessValue(forKey: key) }
|
||||
|
||||
{% if unwrapOptional %}
|
||||
guard let value = primitiveValue(forKey: key) as? {{ rawType }}.RawValue,
|
||||
let result = {{ rawType }}(rawValue: value) else {
|
||||
fatalError("Could not convert value for key '\(key)' to type '{{ rawType }}'")
|
||||
}
|
||||
return result
|
||||
{% else %}
|
||||
guard let value = primitiveValue(forKey: key) as? {{ rawType }}.RawValue else {
|
||||
return nil
|
||||
}
|
||||
return {{ rawType }}(rawValue: value)
|
||||
{% endif %}
|
||||
}
|
||||
set {
|
||||
let key = "{{ attribute.name }}"
|
||||
willChangeValue(forKey: key)
|
||||
defer { didChangeValue(forKey: key) }
|
||||
|
||||
setPrimitiveValue(newValue{% if not unwrapOptional %}?{% endif %}.rawValue, forKey: key)
|
||||
}
|
||||
}
|
||||
{% elif attribute.usesScalarValueType and attribute.isOptional %}
|
||||
{{ accessModifier }} var {{ attribute.name }}: {{ attribute.typeName }}? {
|
||||
get {
|
||||
let key = "{{ attribute.name }}"
|
||||
willAccessValue(forKey: key)
|
||||
defer { didAccessValue(forKey: key) }
|
||||
|
||||
return primitiveValue(forKey: key) as? {{ attribute.typeName }}
|
||||
}
|
||||
set {
|
||||
let key = "{{ attribute.name }}"
|
||||
willChangeValue(forKey: key)
|
||||
defer { didChangeValue(forKey: key) }
|
||||
|
||||
setPrimitiveValue(newValue, forKey: key)
|
||||
}
|
||||
}
|
||||
{% else %}
|
||||
@NSManaged {{ accessModifier }} var {{ attribute.name }}: {{ attribute.typeName }}{% if attribute.isOptional %}?{% endif %}
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
{% for relationship in entity.relationships %}
|
||||
{% if relationship.isToMany %}
|
||||
@NSManaged {{ accessModifier }} var {{ relationship.name }}: {% if relationship.isOrdered %}NSOrderedSet{% else %}Set<{{ model.entities[relationship.destinationEntity].className|default:"NSManagedObject" }}>{% endif %}{% if relationship.isOptional %}?{% endif %}
|
||||
{% else %}
|
||||
@NSManaged {{ accessModifier }} var {{ relationship.name }}: {{ model.entities[relationship.destinationEntity].className|default:"NSManagedObject" }}{% if relationship.isOptional %}?{% endif %}
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
{% for fetchedProperty in entity.fetchedProperties %}
|
||||
@NSManaged {{ accessModifier }} var {{ fetchedProperty.name }}: [{{ fetchedProperty.fetchRequest.entity }}]
|
||||
{% endfor %}
|
||||
// swiftlint:enable discouraged_optional_boolean discouraged_optional_collection
|
||||
}
|
||||
|
||||
{% for relationship in entity.relationships where relationship.isToMany %}
|
||||
{% set destinationEntityClassName %}{{ model.entities[relationship.destinationEntity].className|default:"NSManagedObject" }}{% endset %}
|
||||
{% set collectionClassName %}{% if relationship.isOrdered %}NSOrderedSet{% else %}Set<{{ destinationEntityClassName }}>{% endif %}{% endset %}
|
||||
{% set relationshipName %}{{ relationship.name | upperFirstLetter }}{% endset %}
|
||||
// MARK: Relationship {{ relationshipName }}
|
||||
|
||||
extension {{ entityClassName }} {
|
||||
{% if relationship.isOrdered %}
|
||||
@objc(insertObject:in{{ relationshipName }}AtIndex:)
|
||||
@NSManaged public func insertInto{{ relationshipName }}(_ value: {{ destinationEntityClassName }}, at idx: Int)
|
||||
|
||||
@objc(removeObjectFrom{{ relationshipName }}AtIndex:)
|
||||
@NSManaged public func removeFrom{{ relationshipName }}(at idx: Int)
|
||||
|
||||
@objc(insert{{ relationshipName }}:atIndexes:)
|
||||
@NSManaged public func insertInto{{ relationshipName }}(_ values: [{{ destinationEntityClassName }}], at indexes: NSIndexSet)
|
||||
|
||||
@objc(remove{{ relationshipName }}AtIndexes:)
|
||||
@NSManaged public func removeFrom{{ relationshipName }}(at indexes: NSIndexSet)
|
||||
|
||||
@objc(replaceObjectIn{{ relationshipName }}AtIndex:withObject:)
|
||||
@NSManaged public func replace{{ relationshipName }}(at idx: Int, with value: {{ destinationEntityClassName }})
|
||||
|
||||
@objc(replace{{ relationshipName }}AtIndexes:with{{ relationshipName }}:)
|
||||
@NSManaged public func replace{{ relationshipName }}(at indexes: NSIndexSet, with values: [{{ destinationEntityClassName }}])
|
||||
|
||||
{% endif %}
|
||||
@objc(add{{ relationshipName }}Object:)
|
||||
@NSManaged public func addTo{{ relationshipName }}(_ value: {{ destinationEntityClassName }})
|
||||
|
||||
@objc(remove{{ relationshipName }}Object:)
|
||||
@NSManaged public func removeFrom{{ relationshipName }}(_ value: {{ destinationEntityClassName }})
|
||||
|
||||
@objc(add{{ relationshipName }}:)
|
||||
@NSManaged public func addTo{{ relationshipName }}(_ values: {{ collectionClassName }})
|
||||
|
||||
@objc(remove{{ relationshipName }}:)
|
||||
@NSManaged public func removeFrom{{ relationshipName }}(_ values: {{ collectionClassName }})
|
||||
}
|
||||
|
||||
{% endfor %}
|
||||
{% if model.fetchRequests[entity.name].count > 0 %}
|
||||
// MARK: Fetch Requests
|
||||
|
||||
extension {{ entityClassName }} {
|
||||
{% for fetchRequest in model.fetchRequests[entity.name] %}
|
||||
{% set resultTypeName %}{% filter removeNewlines:"leading" %}
|
||||
{% if fetchRequest.resultType == "Object" %}
|
||||
{{ entityClassName }}
|
||||
{% elif fetchRequest.resultType == "Object ID" %}
|
||||
NSManagedObjectID
|
||||
{% elif fetchRequest.resultType == "Dictionary" %}
|
||||
[String: Any]
|
||||
{% endif %}
|
||||
{% endfilter %}{% endset %}
|
||||
class func fetch{{ fetchRequest.name | upperFirstLetter }}({% filter removeNewlines:"leading" %}
|
||||
managedObjectContext: NSManagedObjectContext
|
||||
{% for variableName, variableType in fetchRequest.substitutionVariables %}
|
||||
, {{ variableName | lowerFirstWord }}: {{ variableType }}
|
||||
{% endfor %}
|
||||
{% endfilter %}) throws -> [{{ resultTypeName }}] {
|
||||
guard let persistentStoreCoordinator = managedObjectContext.persistentStoreCoordinator else {
|
||||
fatalError("Managed object context has no persistent store coordinator for getting fetch request templates")
|
||||
}
|
||||
let model = persistentStoreCoordinator.managedObjectModel
|
||||
let substitutionVariables: [String: Any] = [
|
||||
{% for variableName, variableType in fetchRequest.substitutionVariables %}
|
||||
"{{ variableName }}": {{ variableName | lowerFirstWord }}{{ "," if not forloop.last }}
|
||||
{% empty %}
|
||||
:
|
||||
{% endfor %}
|
||||
]
|
||||
|
||||
guard let fetchRequest = model.fetchRequestFromTemplate(withName: "{{ fetchRequest.name }}", substitutionVariables: substitutionVariables) else {
|
||||
fatalError("No fetch request template named '{{ fetchRequest.name }}' found.")
|
||||
}
|
||||
|
||||
guard let result = try managedObjectContext.fetch(fetchRequest) as? [{{ resultTypeName }}] else {
|
||||
fatalError("Unable to cast fetch result to correct result type.")
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
{% endfor %}
|
||||
}
|
||||
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
{% endfor %}
|
||||
// swiftlint:enable identifier_name line_length type_body_length
|
|
@ -0,0 +1,103 @@
|
|||
// swiftlint:disable all
|
||||
// Generated using SwiftGen — https://github.com/SwiftGen/SwiftGen
|
||||
|
||||
{% if groups.count > 0 %}
|
||||
{% set enumName %}{{param.enumName|default:"Files"}}{% endset %}
|
||||
{% set useExt %}{% if param.useExtension|default:"true" %}true{% endif %}{% endset %}
|
||||
{% set accessModifier %}{% if param.publicAccess %}public{% else %}internal{% endif %}{% endset %}
|
||||
{% set resourceType %}{{param.resourceTypeName|default:"File"}}{% endset %}
|
||||
import Foundation
|
||||
|
||||
// swiftlint:disable superfluous_disable_command file_length line_length implicit_return
|
||||
|
||||
// MARK: - Files
|
||||
|
||||
{% macro groupBlock group %}
|
||||
{% for file in group.files %}
|
||||
{% call fileBlock file %}
|
||||
{% endfor %}
|
||||
{% for dir in group.directories %}
|
||||
{% call dirBlock dir %}
|
||||
{% endfor %}
|
||||
{% endmacro %}
|
||||
{% macro fileBlock file %}
|
||||
/// {% if file.path and param.preservePath %}{{file.path}}/{% endif %}{{file.name}}{% if file.ext %}.{{file.ext}}{% endif %}
|
||||
{% set identifier %}{{ file.name }}{% if useExt %}.{{ file.ext }}{% endif %}{% endset %}
|
||||
{{accessModifier}} static let {{identifier|swiftIdentifier:"pretty"|lowerFirstWord|escapeReservedKeywords}} = {{resourceType}}(name: "{{file.name}}", ext: {% if file.ext %}"{{file.ext}}"{% else %}nil{% endif %}, relativePath: "{{file.path if param.preservePath}}", mimeType: "{{file.mimeType}}")
|
||||
{% endmacro %}
|
||||
{% macro dirBlock directory %}
|
||||
{% for file in directory.files %}
|
||||
{% call fileBlock file %}
|
||||
{% endfor %}
|
||||
{% for dir in directory.directories %}
|
||||
{% call dirBlock dir %}
|
||||
{% endfor %}
|
||||
{% endmacro %}
|
||||
// swiftlint:disable explicit_type_interface identifier_name
|
||||
// swiftlint:disable nesting type_body_length type_name vertical_whitespace_opening_braces
|
||||
{{accessModifier}} enum {{enumName}} {
|
||||
{% if groups.count > 1 or param.forceFileNameEnum %}
|
||||
{% for group in groups %}
|
||||
{{accessModifier}} enum {{group.name|swiftIdentifier:"pretty"|escapeReservedKeywords}} {
|
||||
{% filter indent:2 %}{% call groupBlock group %}{% endfilter %}
|
||||
}
|
||||
{% endfor %}
|
||||
{% else %}
|
||||
{% call groupBlock groups.first %}
|
||||
{% endif %}
|
||||
}
|
||||
// swiftlint:enable explicit_type_interface identifier_name
|
||||
// swiftlint:enable nesting type_body_length type_name vertical_whitespace_opening_braces
|
||||
|
||||
// MARK: - Implementation Details
|
||||
|
||||
{{accessModifier}} struct {{resourceType}} {
|
||||
{{accessModifier}} let name: String
|
||||
{{accessModifier}} let ext: String?
|
||||
{{accessModifier}} let relativePath: String
|
||||
{{accessModifier}} let mimeType: String
|
||||
|
||||
{{accessModifier}} var url: URL {
|
||||
return url(locale: nil)
|
||||
}
|
||||
|
||||
{{accessModifier}} func url(locale: Locale?) -> URL {
|
||||
let bundle = {{param.bundle|default:"BundleToken.bundle"}}
|
||||
let url = bundle.url(
|
||||
forResource: name,
|
||||
withExtension: ext,
|
||||
subdirectory: relativePath,
|
||||
localization: locale?.identifier
|
||||
)
|
||||
guard let result = url else {
|
||||
let file = name + (ext.flatMap { ".\($0)" } ?? "")
|
||||
fatalError("Could not locate file named \(file)")
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
{{accessModifier}} var path: String {
|
||||
return path(locale: nil)
|
||||
}
|
||||
|
||||
{{accessModifier}} func path(locale: Locale?) -> String {
|
||||
return url(locale: locale).path
|
||||
}
|
||||
}
|
||||
{% if not param.bundle %}
|
||||
|
||||
// swiftlint:disable convenience_type explicit_type_interface
|
||||
private final class BundleToken {
|
||||
static let bundle: Bundle = {
|
||||
#if SWIFT_PACKAGE
|
||||
return Bundle.module
|
||||
#else
|
||||
return Bundle(for: BundleToken.self)
|
||||
#endif
|
||||
}()
|
||||
}
|
||||
// swiftlint:enable convenience_type explicit_type_interface
|
||||
{% endif %}
|
||||
{% else %}
|
||||
// No files found
|
||||
{% endif %}
|
|
@ -0,0 +1,103 @@
|
|||
// swiftlint:disable all
|
||||
// Generated using SwiftGen — https://github.com/SwiftGen/SwiftGen
|
||||
|
||||
{% if groups.count > 0 %}
|
||||
{% set enumName %}{{param.enumName|default:"Files"}}{% endset %}
|
||||
{% set useExt %}{% if param.useExtension|default:"true" %}true{% endif %}{% endset %}
|
||||
{% set accessModifier %}{% if param.publicAccess %}public{% else %}internal{% endif %}{% endset %}
|
||||
{% set resourceType %}{{param.resourceTypeName|default:"File"}}{% endset %}
|
||||
import Foundation
|
||||
|
||||
// swiftlint:disable superfluous_disable_command file_length line_length implicit_return
|
||||
|
||||
// MARK: - Files
|
||||
|
||||
{% macro groupBlock group %}
|
||||
{% for file in group.files %}
|
||||
{% call fileBlock file %}
|
||||
{% endfor %}
|
||||
{% for dir in group.directories %}
|
||||
{% call dirBlock dir %}
|
||||
{% endfor %}
|
||||
{% endmacro %}
|
||||
{% macro fileBlock file %}
|
||||
/// {% if file.path and param.preservePath %}{{file.path}}/{% endif %}{{file.name}}{% if file.ext %}.{{file.ext}}{% endif %}
|
||||
{% set identifier %}{{ file.name }}{% if useExt %}.{{ file.ext }}{% endif %}{% endset %}
|
||||
{{accessModifier}} static let {{identifier|swiftIdentifier:"pretty"|lowerFirstWord|escapeReservedKeywords}} = {{resourceType}}(name: "{{file.name}}", ext: {% if file.ext %}"{{file.ext}}"{% else %}nil{% endif %}, relativePath: "{{file.path if param.preservePath}}", mimeType: "{{file.mimeType}}")
|
||||
{% endmacro %}
|
||||
{% macro dirBlock directory %}
|
||||
{% for file in directory.files %}
|
||||
{% call fileBlock file %}
|
||||
{% endfor %}
|
||||
{% for dir in directory.directories %}
|
||||
{% call dirBlock dir %}
|
||||
{% endfor %}
|
||||
{% endmacro %}
|
||||
// swiftlint:disable explicit_type_interface identifier_name
|
||||
// swiftlint:disable nesting type_body_length type_name vertical_whitespace_opening_braces
|
||||
{{accessModifier}} enum {{enumName}} {
|
||||
{% if groups.count > 1 or param.forceFileNameEnum %}
|
||||
{% for group in groups %}
|
||||
{{accessModifier}} enum {{group.name|swiftIdentifier:"pretty"|escapeReservedKeywords}} {
|
||||
{% filter indent:2 %}{% call groupBlock group %}{% endfilter %}
|
||||
}
|
||||
{% endfor %}
|
||||
{% else %}
|
||||
{% call groupBlock groups.first %}
|
||||
{% endif %}
|
||||
}
|
||||
// swiftlint:enable explicit_type_interface identifier_name
|
||||
// swiftlint:enable nesting type_body_length type_name vertical_whitespace_opening_braces
|
||||
|
||||
// MARK: - Implementation Details
|
||||
|
||||
{{accessModifier}} struct {{resourceType}} {
|
||||
{{accessModifier}} let name: String
|
||||
{{accessModifier}} let ext: String?
|
||||
{{accessModifier}} let relativePath: String
|
||||
{{accessModifier}} let mimeType: String
|
||||
|
||||
{{accessModifier}} var url: URL {
|
||||
return url(locale: nil)
|
||||
}
|
||||
|
||||
{{accessModifier}} func url(locale: Locale?) -> URL {
|
||||
let bundle = {{param.bundle|default:"BundleToken.bundle"}}
|
||||
let url = bundle.url(
|
||||
forResource: name,
|
||||
withExtension: ext,
|
||||
subdirectory: relativePath,
|
||||
localization: locale?.identifier
|
||||
)
|
||||
guard let result = url else {
|
||||
let file = name + (ext.flatMap { ".\($0)" } ?? "")
|
||||
fatalError("Could not locate file named \(file)")
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
{{accessModifier}} var path: String {
|
||||
return path(locale: nil)
|
||||
}
|
||||
|
||||
{{accessModifier}} func path(locale: Locale?) -> String {
|
||||
return url(locale: locale).path
|
||||
}
|
||||
}
|
||||
{% if not param.bundle %}
|
||||
|
||||
// swiftlint:disable convenience_type explicit_type_interface
|
||||
private final class BundleToken {
|
||||
static let bundle: Bundle = {
|
||||
#if SWIFT_PACKAGE
|
||||
return Bundle.module
|
||||
#else
|
||||
return Bundle(for: BundleToken.self)
|
||||
#endif
|
||||
}()
|
||||
}
|
||||
// swiftlint:enable convenience_type explicit_type_interface
|
||||
{% endif %}
|
||||
{% else %}
|
||||
// No files found
|
||||
{% endif %}
|
|
@ -0,0 +1,107 @@
|
|||
// swiftlint:disable all
|
||||
// Generated using SwiftGen — https://github.com/SwiftGen/SwiftGen
|
||||
|
||||
{% if groups.count > 0 %}
|
||||
{% set enumName %}{{param.enumName|default:"Files"}}{% endset %}
|
||||
{% set useExt %}{% if param.useExtension|default:"true" %}true{% endif %}{% endset %}
|
||||
{% set accessModifier %}{% if param.publicAccess %}public{% else %}internal{% endif %}{% endset %}
|
||||
{% set resourceType %}{{param.resourceTypeName|default:"File"}}{% endset %}
|
||||
import Foundation
|
||||
|
||||
// swiftlint:disable superfluous_disable_command file_length line_length implicit_return
|
||||
|
||||
// MARK: - Files
|
||||
|
||||
{% macro groupBlock group %}
|
||||
{% for file in group.files %}
|
||||
{% call fileBlock file %}
|
||||
{% endfor %}
|
||||
{% for dir in group.directories %}
|
||||
{% call dirBlock dir "" %}
|
||||
{% endfor %}
|
||||
{% endmacro %}
|
||||
{% macro fileBlock file %}
|
||||
/// {% if file.path and param.preservePath %}{{file.path}}/{% endif %}{{file.name}}{% if file.ext %}.{{file.ext}}{% endif %}
|
||||
{% set identifier %}{{ file.name }}{% if useExt %}.{{ file.ext }}{% endif %}{% endset %}
|
||||
{{accessModifier}} static let {{identifier|swiftIdentifier:"pretty"|lowerFirstWord|escapeReservedKeywords}} = {{resourceType}}(name: "{{file.name}}", ext: {% if file.ext %}"{{file.ext}}"{% else %}nil{% endif %}, relativePath: "{{file.path if param.preservePath}}", mimeType: "{{file.mimeType}}")
|
||||
{% endmacro %}
|
||||
{% macro dirBlock directory parent %}
|
||||
{% set fullDir %}{{parent}}{{directory.name}}/{% endset %}
|
||||
/// {{ fullDir }}
|
||||
{{accessModifier}} enum {{directory.name|swiftIdentifier:"pretty"|escapeReservedKeywords}} {
|
||||
{% for file in directory.files %}
|
||||
{% filter indent:2 %}{% call fileBlock file %}{% endfilter %}
|
||||
{% endfor %}
|
||||
{% for dir in directory.directories %}
|
||||
{% filter indent:2 %}{% call dirBlock dir fullDir %}{% endfilter %}
|
||||
{% endfor %}
|
||||
}
|
||||
{% endmacro %}
|
||||
// swiftlint:disable explicit_type_interface identifier_name
|
||||
// swiftlint:disable nesting type_body_length type_name vertical_whitespace_opening_braces
|
||||
{{accessModifier}} enum {{enumName}} {
|
||||
{% if groups.count > 1 or param.forceFileNameEnum %}
|
||||
{% for group in groups %}
|
||||
{{accessModifier}} enum {{group.name|swiftIdentifier:"pretty"|escapeReservedKeywords}} {
|
||||
{% filter indent:2 %}{% call groupBlock group %}{% endfilter %}
|
||||
}
|
||||
{% endfor %}
|
||||
{% else %}
|
||||
{% call groupBlock groups.first %}
|
||||
{% endif %}
|
||||
}
|
||||
// swiftlint:enable explicit_type_interface identifier_name
|
||||
// swiftlint:enable nesting type_body_length type_name vertical_whitespace_opening_braces
|
||||
|
||||
// MARK: - Implementation Details
|
||||
|
||||
{{accessModifier}} struct {{resourceType}} {
|
||||
{{accessModifier}} let name: String
|
||||
{{accessModifier}} let ext: String?
|
||||
{{accessModifier}} let relativePath: String
|
||||
{{accessModifier}} let mimeType: String
|
||||
|
||||
{{accessModifier}} var url: URL {
|
||||
return url(locale: nil)
|
||||
}
|
||||
|
||||
{{accessModifier}} func url(locale: Locale?) -> URL {
|
||||
let bundle = {{param.bundle|default:"BundleToken.bundle"}}
|
||||
let url = bundle.url(
|
||||
forResource: name,
|
||||
withExtension: ext,
|
||||
subdirectory: relativePath,
|
||||
localization: locale?.identifier
|
||||
)
|
||||
guard let result = url else {
|
||||
let file = name + (ext.flatMap { ".\($0)" } ?? "")
|
||||
fatalError("Could not locate file named \(file)")
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
{{accessModifier}} var path: String {
|
||||
return path(locale: nil)
|
||||
}
|
||||
|
||||
{{accessModifier}} func path(locale: Locale?) -> String {
|
||||
return url(locale: locale).path
|
||||
}
|
||||
}
|
||||
{% if not param.bundle %}
|
||||
|
||||
// swiftlint:disable convenience_type explicit_type_interface
|
||||
private final class BundleToken {
|
||||
static let bundle: Bundle = {
|
||||
#if SWIFT_PACKAGE
|
||||
return Bundle.module
|
||||
#else
|
||||
return Bundle(for: BundleToken.self)
|
||||
#endif
|
||||
}()
|
||||
}
|
||||
// swiftlint:enable convenience_type explicit_type_interface
|
||||
{% endif %}
|
||||
{% else %}
|
||||
// No files found
|
||||
{% endif %}
|
|
@ -0,0 +1,107 @@
|
|||
// swiftlint:disable all
|
||||
// Generated using SwiftGen — https://github.com/SwiftGen/SwiftGen
|
||||
|
||||
{% if groups.count > 0 %}
|
||||
{% set enumName %}{{param.enumName|default:"Files"}}{% endset %}
|
||||
{% set useExt %}{% if param.useExtension|default:"true" %}true{% endif %}{% endset %}
|
||||
{% set accessModifier %}{% if param.publicAccess %}public{% else %}internal{% endif %}{% endset %}
|
||||
{% set resourceType %}{{param.resourceTypeName|default:"File"}}{% endset %}
|
||||
import Foundation
|
||||
|
||||
// swiftlint:disable superfluous_disable_command file_length line_length implicit_return
|
||||
|
||||
// MARK: - Files
|
||||
|
||||
{% macro groupBlock group %}
|
||||
{% for file in group.files %}
|
||||
{% call fileBlock file %}
|
||||
{% endfor %}
|
||||
{% for dir in group.directories %}
|
||||
{% call dirBlock dir "" %}
|
||||
{% endfor %}
|
||||
{% endmacro %}
|
||||
{% macro fileBlock file %}
|
||||
/// {% if file.path and param.preservePath %}{{file.path}}/{% endif %}{{file.name}}{% if file.ext %}.{{file.ext}}{% endif %}
|
||||
{% set identifier %}{{ file.name }}{% if useExt %}.{{ file.ext }}{% endif %}{% endset %}
|
||||
{{accessModifier}} static let {{identifier|swiftIdentifier:"pretty"|lowerFirstWord|escapeReservedKeywords}} = {{resourceType}}(name: "{{file.name}}", ext: {% if file.ext %}"{{file.ext}}"{% else %}nil{% endif %}, relativePath: "{{file.path if param.preservePath}}", mimeType: "{{file.mimeType}}")
|
||||
{% endmacro %}
|
||||
{% macro dirBlock directory parent %}
|
||||
{% set fullDir %}{{parent}}{{directory.name}}/{% endset %}
|
||||
/// {{ fullDir }}
|
||||
{{accessModifier}} enum {{directory.name|swiftIdentifier:"pretty"|escapeReservedKeywords}} {
|
||||
{% for file in directory.files %}
|
||||
{% filter indent:2 %}{% call fileBlock file %}{% endfilter %}
|
||||
{% endfor %}
|
||||
{% for dir in directory.directories %}
|
||||
{% filter indent:2 %}{% call dirBlock dir fullDir %}{% endfilter %}
|
||||
{% endfor %}
|
||||
}
|
||||
{% endmacro %}
|
||||
// swiftlint:disable explicit_type_interface identifier_name
|
||||
// swiftlint:disable nesting type_body_length type_name vertical_whitespace_opening_braces
|
||||
{{accessModifier}} enum {{enumName}} {
|
||||
{% if groups.count > 1 or param.forceFileNameEnum %}
|
||||
{% for group in groups %}
|
||||
{{accessModifier}} enum {{group.name|swiftIdentifier:"pretty"|escapeReservedKeywords}} {
|
||||
{% filter indent:2 %}{% call groupBlock group %}{% endfilter %}
|
||||
}
|
||||
{% endfor %}
|
||||
{% else %}
|
||||
{% call groupBlock groups.first %}
|
||||
{% endif %}
|
||||
}
|
||||
// swiftlint:enable explicit_type_interface identifier_name
|
||||
// swiftlint:enable nesting type_body_length type_name vertical_whitespace_opening_braces
|
||||
|
||||
// MARK: - Implementation Details
|
||||
|
||||
{{accessModifier}} struct {{resourceType}} {
|
||||
{{accessModifier}} let name: String
|
||||
{{accessModifier}} let ext: String?
|
||||
{{accessModifier}} let relativePath: String
|
||||
{{accessModifier}} let mimeType: String
|
||||
|
||||
{{accessModifier}} var url: URL {
|
||||
return url(locale: nil)
|
||||
}
|
||||
|
||||
{{accessModifier}} func url(locale: Locale?) -> URL {
|
||||
let bundle = {{param.bundle|default:"BundleToken.bundle"}}
|
||||
let url = bundle.url(
|
||||
forResource: name,
|
||||
withExtension: ext,
|
||||
subdirectory: relativePath,
|
||||
localization: locale?.identifier
|
||||
)
|
||||
guard let result = url else {
|
||||
let file = name + (ext.flatMap { ".\($0)" } ?? "")
|
||||
fatalError("Could not locate file named \(file)")
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
{{accessModifier}} var path: String {
|
||||
return path(locale: nil)
|
||||
}
|
||||
|
||||
{{accessModifier}} func path(locale: Locale?) -> String {
|
||||
return url(locale: locale).path
|
||||
}
|
||||
}
|
||||
{% if not param.bundle %}
|
||||
|
||||
// swiftlint:disable convenience_type explicit_type_interface
|
||||
private final class BundleToken {
|
||||
static let bundle: Bundle = {
|
||||
#if SWIFT_PACKAGE
|
||||
return Bundle.module
|
||||
#else
|
||||
return Bundle(for: BundleToken.self)
|
||||
#endif
|
||||
}()
|
||||
}
|
||||
// swiftlint:enable convenience_type explicit_type_interface
|
||||
{% endif %}
|
||||
{% else %}
|
||||
// No files found
|
||||
{% endif %}
|
|
@ -0,0 +1,110 @@
|
|||
// swiftlint:disable all
|
||||
// Generated using SwiftGen — https://github.com/SwiftGen/SwiftGen
|
||||
|
||||
{% if families %}
|
||||
{% set accessModifier %}{% if param.publicAccess %}public{% else %}internal{% endif %}{% endset %}
|
||||
{% set fontType %}{{param.fontTypeName|default:"FontConvertible"}}{% endset %}
|
||||
#if os(macOS)
|
||||
import AppKit.NSFont
|
||||
#elseif os(iOS) || os(tvOS) || os(watchOS)
|
||||
import UIKit.UIFont
|
||||
#endif
|
||||
|
||||
// Deprecated typealiases
|
||||
@available(*, deprecated, renamed: "{{fontType}}.Font", message: "This typealias will be removed in SwiftGen 7.0")
|
||||
{{accessModifier}} typealias {{param.fontAliasName|default:"Font"}} = {{fontType}}.Font
|
||||
|
||||
// swiftlint:disable superfluous_disable_command
|
||||
// swiftlint:disable file_length
|
||||
// swiftlint:disable implicit_return
|
||||
|
||||
// MARK: - Fonts
|
||||
|
||||
// swiftlint:disable identifier_name line_length type_body_length
|
||||
{% macro transformPath path %}{% filter removeNewlines %}
|
||||
{% if param.preservePath %}
|
||||
{{path}}
|
||||
{% else %}
|
||||
{{path|basename}}
|
||||
{% endif %}
|
||||
{% endfilter %}{% endmacro %}
|
||||
{{accessModifier}} enum {{param.enumName|default:"FontFamily"}} {
|
||||
{% for family in families %}
|
||||
{{accessModifier}} enum {{family.name|swiftIdentifier:"pretty"|escapeReservedKeywords}} {
|
||||
{% for font in family.fonts %}
|
||||
{{accessModifier}} static let {{font.style|swiftIdentifier:"pretty"|lowerFirstWord|escapeReservedKeywords}} = {{fontType}}(name: "{{font.name}}", family: "{{family.name}}", path: "{% call transformPath font.path %}")
|
||||
{% endfor %}
|
||||
{{accessModifier}} static let all: [{{fontType}}] = [{% for font in family.fonts %}{{font.style|swiftIdentifier:"pretty"|lowerFirstWord|escapeReservedKeywords}}{{ ", " if not forloop.last }}{% endfor %}]
|
||||
}
|
||||
{% endfor %}
|
||||
{{accessModifier}} static let allCustomFonts: [{{fontType}}] = [{% for family in families %}{{family.name|swiftIdentifier:"pretty"|escapeReservedKeywords}}.all{{ ", " if not forloop.last }}{% endfor %}].flatMap { $0 }
|
||||
{{accessModifier}} static func registerAllCustomFonts() {
|
||||
allCustomFonts.forEach { $0.register() }
|
||||
}
|
||||
}
|
||||
// swiftlint:enable identifier_name line_length type_body_length
|
||||
|
||||
// MARK: - Implementation Details
|
||||
|
||||
{{accessModifier}} struct {{fontType}} {
|
||||
{{accessModifier}} let name: String
|
||||
{{accessModifier}} let family: String
|
||||
{{accessModifier}} let path: String
|
||||
|
||||
#if os(macOS)
|
||||
{{accessModifier}} typealias Font = NSFont
|
||||
#elseif os(iOS) || os(tvOS) || os(watchOS)
|
||||
{{accessModifier}} typealias Font = UIFont
|
||||
#endif
|
||||
|
||||
{{accessModifier}} func font(size: CGFloat) -> Font! {
|
||||
return Font(font: self, size: size)
|
||||
}
|
||||
|
||||
{{accessModifier}} func register() {
|
||||
// swiftlint:disable:next conditional_returns_on_newline
|
||||
guard let url = url else { return }
|
||||
CTFontManagerRegisterFontsForURL(url as CFURL, .process, nil)
|
||||
}
|
||||
|
||||
fileprivate var url: URL? {
|
||||
{% if param.lookupFunction %}
|
||||
return {{param.lookupFunction}}(name, family, path)
|
||||
{% else %}
|
||||
return {{param.bundle|default:"BundleToken.bundle"}}.url(forResource: path, withExtension: nil)
|
||||
{% endif %}
|
||||
}
|
||||
}
|
||||
|
||||
{{accessModifier}} extension {{fontType}}.Font {
|
||||
convenience init?(font: {{fontType}}, size: CGFloat) {
|
||||
#if os(iOS) || os(tvOS) || os(watchOS)
|
||||
if !UIFont.fontNames(forFamilyName: font.family).contains(font.name) {
|
||||
font.register()
|
||||
}
|
||||
#elseif os(macOS)
|
||||
if let url = font.url, CTFontManagerGetScopeForURL(url as CFURL) == .none {
|
||||
font.register()
|
||||
}
|
||||
#endif
|
||||
|
||||
self.init(name: font.name, size: size)
|
||||
}
|
||||
}
|
||||
{% if not param.bundle and not param.lookupFunction %}
|
||||
|
||||
// swiftlint:disable convenience_type
|
||||
private final class BundleToken {
|
||||
static let bundle: Bundle = {
|
||||
#if SWIFT_PACKAGE
|
||||
return Bundle.module
|
||||
#else
|
||||
return Bundle(for: BundleToken.self)
|
||||
#endif
|
||||
}()
|
||||
}
|
||||
// swiftlint:enable convenience_type
|
||||
{% endif %}
|
||||
{% else %}
|
||||
// No fonts found
|
||||
{% endif %}
|
|
@ -0,0 +1,113 @@
|
|||
// swiftlint:disable all
|
||||
// Generated using SwiftGen — https://github.com/SwiftGen/SwiftGen
|
||||
|
||||
{% if families %}
|
||||
{% set accessModifier %}{% if param.publicAccess %}public{% else %}internal{% endif %}{% endset %}
|
||||
{% set fontType %}{{param.fontTypeName|default:"FontConvertible"}}{% endset %}
|
||||
#if os(macOS)
|
||||
import AppKit.NSFont
|
||||
#elseif os(iOS) || os(tvOS) || os(watchOS)
|
||||
import UIKit.UIFont
|
||||
#endif
|
||||
|
||||
// Deprecated typealiases
|
||||
@available(*, deprecated, renamed: "{{fontType}}.Font", message: "This typealias will be removed in SwiftGen 7.0")
|
||||
{{accessModifier}} typealias {{param.fontAliasName|default:"Font"}} = {{fontType}}.Font
|
||||
|
||||
// swiftlint:disable superfluous_disable_command
|
||||
// swiftlint:disable file_length
|
||||
|
||||
// MARK: - Fonts
|
||||
|
||||
// swiftlint:disable identifier_name line_length type_body_length
|
||||
{% macro transformPath path %}{% filter removeNewlines %}
|
||||
{% if param.preservePath %}
|
||||
{{path}}
|
||||
{% else %}
|
||||
{{path|basename}}
|
||||
{% endif %}
|
||||
{% endfilter %}{% endmacro %}
|
||||
{{accessModifier}} enum {{param.enumName|default:"FontFamily"}} {
|
||||
{% for family in families %}
|
||||
{{accessModifier}} enum {{family.name|swiftIdentifier:"pretty"|escapeReservedKeywords}} {
|
||||
{% for font in family.fonts %}
|
||||
{{accessModifier}} static let {{font.style|swiftIdentifier:"pretty"|lowerFirstWord|escapeReservedKeywords}} = {{fontType}}(name: "{{font.name}}", family: "{{family.name}}", path: "{% call transformPath font.path %}")
|
||||
{% endfor %}
|
||||
{{accessModifier}} static let all: [{{fontType}}] = [{% for font in family.fonts %}{{font.style|swiftIdentifier:"pretty"|lowerFirstWord|escapeReservedKeywords}}{{ ", " if not forloop.last }}{% endfor %}]
|
||||
}
|
||||
{% endfor %}
|
||||
{{accessModifier}} static let allCustomFonts: [{{fontType}}] = [{% for family in families %}{{family.name|swiftIdentifier:"pretty"|escapeReservedKeywords}}.all{{ ", " if not forloop.last }}{% endfor %}].flatMap { $0 }
|
||||
{{accessModifier}} static func registerAllCustomFonts() {
|
||||
allCustomFonts.forEach { $0.register() }
|
||||
}
|
||||
}
|
||||
// swiftlint:enable identifier_name line_length type_body_length
|
||||
|
||||
// MARK: - Implementation Details
|
||||
|
||||
{{accessModifier}} struct {{fontType}} {
|
||||
{{accessModifier}} let name: String
|
||||
{{accessModifier}} let family: String
|
||||
{{accessModifier}} let path: String
|
||||
|
||||
#if os(macOS)
|
||||
{{accessModifier}} typealias Font = NSFont
|
||||
#elseif os(iOS) || os(tvOS) || os(watchOS)
|
||||
{{accessModifier}} typealias Font = UIFont
|
||||
#endif
|
||||
|
||||
{{accessModifier}} func font(size: CGFloat) -> Font {
|
||||
guard let font = Font(font: self, size: size) else {
|
||||
fatalError("Unable to initialize font '\(name)' (\(family))")
|
||||
}
|
||||
return font
|
||||
}
|
||||
|
||||
{{accessModifier}} func register() {
|
||||
// swiftlint:disable:next conditional_returns_on_newline
|
||||
guard let url = url else { return }
|
||||
CTFontManagerRegisterFontsForURL(url as CFURL, .process, nil)
|
||||
}
|
||||
|
||||
fileprivate var url: URL? {
|
||||
// swiftlint:disable:next implicit_return
|
||||
{% if param.lookupFunction %}
|
||||
return {{param.lookupFunction}}(name, family, path)
|
||||
{% else %}
|
||||
return {{param.bundle|default:"BundleToken.bundle"}}.url(forResource: path, withExtension: nil)
|
||||
{% endif %}
|
||||
}
|
||||
}
|
||||
|
||||
{{accessModifier}} extension {{fontType}}.Font {
|
||||
convenience init?(font: {{fontType}}, size: CGFloat) {
|
||||
#if os(iOS) || os(tvOS) || os(watchOS)
|
||||
if !UIFont.fontNames(forFamilyName: font.family).contains(font.name) {
|
||||
font.register()
|
||||
}
|
||||
#elseif os(macOS)
|
||||
if let url = font.url, CTFontManagerGetScopeForURL(url as CFURL) == .none {
|
||||
font.register()
|
||||
}
|
||||
#endif
|
||||
|
||||
self.init(name: font.name, size: size)
|
||||
}
|
||||
}
|
||||
{% if not param.bundle and not param.lookupFunction %}
|
||||
|
||||
// swiftlint:disable convenience_type
|
||||
private final class BundleToken {
|
||||
static let bundle: Bundle = {
|
||||
#if SWIFT_PACKAGE
|
||||
return Bundle.module
|
||||
#else
|
||||
return Bundle(for: BundleToken.self)
|
||||
#endif
|
||||
}()
|
||||
}
|
||||
// swiftlint:enable convenience_type
|
||||
{% endif %}
|
||||
{% else %}
|
||||
// No fonts found
|
||||
{% endif %}
|
|
@ -0,0 +1,157 @@
|
|||
// swiftlint:disable all
|
||||
// Generated using SwiftGen — https://github.com/SwiftGen/SwiftGen
|
||||
|
||||
{% if platform and storyboards %}
|
||||
{% set accessModifier %}{% if param.publicAccess %}public{% else %}internal{% endif %}{% endset %}
|
||||
{% set isAppKit %}{% if platform == "macOS" %}true{% endif %}{% endset %}
|
||||
{% set prefix %}{% if isAppKit %}NS{% else %}UI{% endif %}{% endset %}
|
||||
{% set controller %}{% if isAppKit %}Controller{% else %}ViewController{% endif %}{% endset %}
|
||||
// swiftlint:disable sorted_imports
|
||||
import Foundation
|
||||
{% for module in modules where module != env.PRODUCT_MODULE_NAME and module != param.module %}
|
||||
import {{module}}
|
||||
{% endfor %}
|
||||
|
||||
// swiftlint:disable superfluous_disable_command
|
||||
// swiftlint:disable file_length implicit_return
|
||||
|
||||
// MARK: - Storyboard Scenes
|
||||
|
||||
// swiftlint:disable explicit_type_interface identifier_name line_length type_body_length type_name
|
||||
{% macro moduleName item %}{% filter removeNewlines %}
|
||||
{% if item.moduleIsPlaceholder %}
|
||||
{{ env.PRODUCT_MODULE_NAME|default:param.module }}
|
||||
{% else %}
|
||||
{{ item.module }}
|
||||
{% endif %}
|
||||
{% endfilter %}{% endmacro %}
|
||||
{% macro className item %}{% filter removeNewlines %}
|
||||
{% set module %}{% call moduleName item %}{% endset %}
|
||||
{% if module and ( not param.ignoreTargetModule or module != env.PRODUCT_MODULE_NAME and module != param.module ) %}
|
||||
{{module}}.
|
||||
{% endif %}
|
||||
{{item.type}}
|
||||
{% endfilter %}{% endmacro %}
|
||||
{{accessModifier}} enum {{param.enumName|default:"StoryboardScene"}} {
|
||||
{% for storyboard in storyboards %}
|
||||
{% set storyboardName %}{{storyboard.name|swiftIdentifier:"pretty"|escapeReservedKeywords}}{% endset %}
|
||||
{{accessModifier}} enum {{storyboardName}}: StoryboardType {
|
||||
{{accessModifier}} static let storyboardName = "{{storyboard.name}}"
|
||||
{% if storyboard.initialScene %}
|
||||
|
||||
{% set sceneClass %}{% call className storyboard.initialScene %}{% endset %}
|
||||
{{accessModifier}} static let initialScene = InitialSceneType<{{sceneClass}}>(storyboard: {{storyboardName}}.self)
|
||||
{% endif %}
|
||||
{% for scene in storyboard.scenes %}
|
||||
|
||||
{% set sceneID %}{{scene.identifier|swiftIdentifier:"pretty"|lowerFirstWord|escapeReservedKeywords}}{% endset %}
|
||||
{% set sceneClass %}{% call className scene %}{% endset %}
|
||||
{{accessModifier}} static let {{sceneID}} = SceneType<{{sceneClass}}>(storyboard: {{storyboardName}}.self, identifier: "{{scene.identifier}}")
|
||||
{% endfor %}
|
||||
}
|
||||
{% endfor %}
|
||||
}
|
||||
// swiftlint:enable explicit_type_interface identifier_name line_length type_body_length type_name
|
||||
|
||||
// MARK: - Implementation Details
|
||||
|
||||
{{accessModifier}} protocol StoryboardType {
|
||||
static var storyboardName: String { get }
|
||||
}
|
||||
|
||||
{{accessModifier}} extension StoryboardType {
|
||||
static var storyboard: {{prefix}}Storyboard {
|
||||
let name = {% if isAppKit %}NSStoryboard.Name({% endif %}self.storyboardName{% if isAppKit %}){% endif %}
|
||||
{% if param.lookupFunction %}
|
||||
return {{param.lookupFunction}}(name)
|
||||
{% else %}
|
||||
return {{prefix}}Storyboard(name: name, bundle: {{param.bundle|default:"BundleToken.bundle"}})
|
||||
{% endif %}
|
||||
}
|
||||
}
|
||||
|
||||
{{accessModifier}} struct SceneType<T{% if not isAppKit %}: UIViewController{% endif %}> {
|
||||
{{accessModifier}} let storyboard: StoryboardType.Type
|
||||
{{accessModifier}} let identifier: String
|
||||
|
||||
{{accessModifier}} func instantiate() -> T {
|
||||
let identifier = {% if isAppKit %}NSStoryboard.SceneIdentifier({% endif %}self.identifier{% if isAppKit %}){% endif %}
|
||||
guard let controller = storyboard.storyboard.instantiate{{controller}}(withIdentifier: identifier) as? T else {
|
||||
fatalError("{{controller}} '\(identifier)' is not of the expected class \(T.self).")
|
||||
}
|
||||
return controller
|
||||
}
|
||||
|
||||
{% if isAppKit %}
|
||||
@available(macOS 10.15, *)
|
||||
{{accessModifier}} func instantiate(creator block: @escaping (NSCoder) -> T?) -> T where T: NSViewController {
|
||||
return storyboard.storyboard.instantiate{{controller}}(identifier: identifier, creator: block)
|
||||
}
|
||||
|
||||
@available(macOS 10.15, *)
|
||||
{{accessModifier}} func instantiate(creator block: @escaping (NSCoder) -> T?) -> T where T: NSWindowController {
|
||||
return storyboard.storyboard.instantiate{{controller}}(identifier: identifier, creator: block)
|
||||
}
|
||||
{% else %}
|
||||
@available(iOS 13.0, tvOS 13.0, *)
|
||||
{{accessModifier}} func instantiate(creator block: @escaping (NSCoder) -> T?) -> T {
|
||||
return storyboard.storyboard.instantiate{{controller}}(identifier: identifier, creator: block)
|
||||
}
|
||||
{% endif %}
|
||||
}
|
||||
|
||||
{{accessModifier}} struct InitialSceneType<T{% if not isAppKit %}: UIViewController{% endif %}> {
|
||||
{{accessModifier}} let storyboard: StoryboardType.Type
|
||||
|
||||
{{accessModifier}} func instantiate() -> T {
|
||||
guard let controller = storyboard.storyboard.instantiateInitial{{controller}}() as? T else {
|
||||
fatalError("{{controller}} is not of the expected class \(T.self).")
|
||||
}
|
||||
return controller
|
||||
}
|
||||
|
||||
{% if isAppKit %}
|
||||
@available(macOS 10.15, *)
|
||||
{{accessModifier}} func instantiate(creator block: @escaping (NSCoder) -> T?) -> T where T: NSViewController {
|
||||
guard let controller = storyboard.storyboard.instantiateInitial{{controller}}(creator: block) else {
|
||||
fatalError("Storyboard \(storyboard.storyboardName) does not have an initial scene.")
|
||||
}
|
||||
return controller
|
||||
}
|
||||
|
||||
@available(macOS 10.15, *)
|
||||
{{accessModifier}} func instantiate(creator block: @escaping (NSCoder) -> T?) -> T where T: NSWindowController {
|
||||
guard let controller = storyboard.storyboard.instantiateInitial{{controller}}(creator: block) else {
|
||||
fatalError("Storyboard \(storyboard.storyboardName) does not have an initial scene.")
|
||||
}
|
||||
return controller
|
||||
}
|
||||
{% else %}
|
||||
@available(iOS 13.0, tvOS 13.0, *)
|
||||
{{accessModifier}} func instantiate(creator block: @escaping (NSCoder) -> T?) -> T {
|
||||
guard let controller = storyboard.storyboard.instantiateInitial{{controller}}(creator: block) else {
|
||||
fatalError("Storyboard \(storyboard.storyboardName) does not have an initial scene.")
|
||||
}
|
||||
return controller
|
||||
}
|
||||
{% endif %}
|
||||
}
|
||||
{% if not param.bundle and not param.lookupFunction %}
|
||||
|
||||
// swiftlint:disable convenience_type
|
||||
private final class BundleToken {
|
||||
static let bundle: Bundle = {
|
||||
#if SWIFT_PACKAGE
|
||||
return Bundle.module
|
||||
#else
|
||||
return Bundle(for: BundleToken.self)
|
||||
#endif
|
||||
}()
|
||||
}
|
||||
// swiftlint:enable convenience_type
|
||||
{% endif %}
|
||||
{% elif storyboards %}
|
||||
// Mixed AppKit and UIKit storyboard files found, please invoke swiftgen with these separately
|
||||
{% else %}
|
||||
// No storyboard found
|
||||
{% endif %}
|
|
@ -0,0 +1,159 @@
|
|||
// swiftlint:disable all
|
||||
// Generated using SwiftGen — https://github.com/SwiftGen/SwiftGen
|
||||
|
||||
{% if platform and storyboards %}
|
||||
{% set accessModifier %}{% if param.publicAccess %}public{% else %}internal{% endif %}{% endset %}
|
||||
{% set isAppKit %}{% if platform == "macOS" %}true{% endif %}{% endset %}
|
||||
{% set prefix %}{% if isAppKit %}NS{% else %}UI{% endif %}{% endset %}
|
||||
{% set controller %}{% if isAppKit %}Controller{% else %}ViewController{% endif %}{% endset %}
|
||||
// swiftlint:disable sorted_imports
|
||||
import Foundation
|
||||
{% for module in modules where module != env.PRODUCT_MODULE_NAME and module != param.module %}
|
||||
import {{module}}
|
||||
{% endfor %}
|
||||
|
||||
// swiftlint:disable superfluous_disable_command
|
||||
// swiftlint:disable file_length implicit_return
|
||||
|
||||
// MARK: - Storyboard Scenes
|
||||
|
||||
// swiftlint:disable explicit_type_interface identifier_name line_length type_body_length type_name
|
||||
{% macro moduleName item %}{% filter removeNewlines %}
|
||||
{% if item.moduleIsPlaceholder %}
|
||||
{{ env.PRODUCT_MODULE_NAME|default:param.module }}
|
||||
{% else %}
|
||||
{{ item.module }}
|
||||
{% endif %}
|
||||
{% endfilter %}{% endmacro %}
|
||||
{% macro className item %}{% filter removeNewlines %}
|
||||
{% set module %}{% call moduleName item %}{% endset %}
|
||||
{% if module and ( not param.ignoreTargetModule or module != env.PRODUCT_MODULE_NAME and module != param.module ) %}
|
||||
{{module}}.
|
||||
{% endif %}
|
||||
{{item.type}}
|
||||
{% endfilter %}{% endmacro %}
|
||||
{{accessModifier}} enum {{param.enumName|default:"StoryboardScene"}} {
|
||||
{% for storyboard in storyboards %}
|
||||
{% set storyboardName %}{{storyboard.name|swiftIdentifier:"pretty"|escapeReservedKeywords}}{% endset %}
|
||||
{{accessModifier}} enum {{storyboardName}}: StoryboardType {
|
||||
{{accessModifier}} static let storyboardName = "{{storyboard.name}}"
|
||||
{% if storyboard.initialScene %}
|
||||
|
||||
{% set sceneClass %}{% call className storyboard.initialScene %}{% endset %}
|
||||
{{accessModifier}} static let initialScene = InitialSceneType<{{sceneClass}}>(storyboard: {{storyboardName}}.self)
|
||||
{% endif %}
|
||||
{% for scene in storyboard.scenes %}
|
||||
|
||||
{% set sceneID %}{{scene.identifier|swiftIdentifier:"pretty"|lowerFirstWord|escapeReservedKeywords}}{% endset %}
|
||||
{% set sceneClass %}{% call className scene %}{% endset %}
|
||||
{{accessModifier}} static let {{sceneID}} = SceneType<{{sceneClass}}>(storyboard: {{storyboardName}}.self, identifier: "{{scene.identifier}}")
|
||||
{% endfor %}
|
||||
}
|
||||
{% endfor %}
|
||||
}
|
||||
// swiftlint:enable explicit_type_interface identifier_name line_length type_body_length type_name
|
||||
|
||||
// MARK: - Implementation Details
|
||||
|
||||
{{accessModifier}} protocol StoryboardType {
|
||||
static var storyboardName: String { get }
|
||||
}
|
||||
|
||||
{{accessModifier}} extension StoryboardType {
|
||||
static var storyboard: {{prefix}}Storyboard {
|
||||
let name = {% if isAppKit %}NSStoryboard.Name({% endif %}self.storyboardName{% if isAppKit %}){% endif %}
|
||||
{% if param.lookupFunction %}
|
||||
return {{param.lookupFunction}}(name)
|
||||
{% else %}
|
||||
return {{prefix}}Storyboard(name: name, bundle: {{param.bundle|default:"BundleToken.bundle"}})
|
||||
{% endif %}
|
||||
}
|
||||
}
|
||||
|
||||
{{accessModifier}} struct SceneType<T{% if not isAppKit %}: UIViewController{% endif %}> {
|
||||
{{accessModifier}} let storyboard: StoryboardType.Type
|
||||
{{accessModifier}} let identifier: String
|
||||
|
||||
{{accessModifier}} func instantiate() -> T {
|
||||
let identifier = {% if isAppKit %}NSStoryboard.SceneIdentifier({% endif %}self.identifier{% if isAppKit %}){% endif %}
|
||||
guard let controller = storyboard.storyboard.instantiate{{controller}}(withIdentifier: identifier) as? T else {
|
||||
fatalError("{{controller}} '\(identifier)' is not of the expected class \(T.self).")
|
||||
}
|
||||
return controller
|
||||
}
|
||||
|
||||
{% if isAppKit %}
|
||||
@available(macOS 10.15, *)
|
||||
{{accessModifier}} func instantiate(creator block: @escaping (NSCoder) -> T?) -> T where T: NSViewController {
|
||||
let identifier = NSStoryboard.SceneIdentifier(self.identifier)
|
||||
return storyboard.storyboard.instantiate{{controller}}(identifier: identifier, creator: block)
|
||||
}
|
||||
|
||||
@available(macOS 10.15, *)
|
||||
{{accessModifier}} func instantiate(creator block: @escaping (NSCoder) -> T?) -> T where T: NSWindowController {
|
||||
let identifier = NSStoryboard.SceneIdentifier(self.identifier)
|
||||
return storyboard.storyboard.instantiate{{controller}}(identifier: identifier, creator: block)
|
||||
}
|
||||
{% else %}
|
||||
@available(iOS 13.0, tvOS 13.0, *)
|
||||
{{accessModifier}} func instantiate(creator block: @escaping (NSCoder) -> T?) -> T {
|
||||
return storyboard.storyboard.instantiate{{controller}}(identifier: identifier, creator: block)
|
||||
}
|
||||
{% endif %}
|
||||
}
|
||||
|
||||
{{accessModifier}} struct InitialSceneType<T{% if not isAppKit %}: UIViewController{% endif %}> {
|
||||
{{accessModifier}} let storyboard: StoryboardType.Type
|
||||
|
||||
{{accessModifier}} func instantiate() -> T {
|
||||
guard let controller = storyboard.storyboard.instantiateInitial{{controller}}() as? T else {
|
||||
fatalError("{{controller}} is not of the expected class \(T.self).")
|
||||
}
|
||||
return controller
|
||||
}
|
||||
|
||||
{% if isAppKit %}
|
||||
@available(macOS 10.15, *)
|
||||
{{accessModifier}} func instantiate(creator block: @escaping (NSCoder) -> T?) -> T where T: NSViewController {
|
||||
guard let controller = storyboard.storyboard.instantiateInitial{{controller}}(creator: block) else {
|
||||
fatalError("Storyboard \(storyboard.storyboardName) does not have an initial scene.")
|
||||
}
|
||||
return controller
|
||||
}
|
||||
|
||||
@available(macOS 10.15, *)
|
||||
{{accessModifier}} func instantiate(creator block: @escaping (NSCoder) -> T?) -> T where T: NSWindowController {
|
||||
guard let controller = storyboard.storyboard.instantiateInitial{{controller}}(creator: block) else {
|
||||
fatalError("Storyboard \(storyboard.storyboardName) does not have an initial scene.")
|
||||
}
|
||||
return controller
|
||||
}
|
||||
{% else %}
|
||||
@available(iOS 13.0, tvOS 13.0, *)
|
||||
{{accessModifier}} func instantiate(creator block: @escaping (NSCoder) -> T?) -> T {
|
||||
guard let controller = storyboard.storyboard.instantiateInitial{{controller}}(creator: block) else {
|
||||
fatalError("Storyboard \(storyboard.storyboardName) does not have an initial scene.")
|
||||
}
|
||||
return controller
|
||||
}
|
||||
{% endif %}
|
||||
}
|
||||
{% if not param.bundle and not param.lookupFunction %}
|
||||
|
||||
// swiftlint:disable convenience_type
|
||||
private final class BundleToken {
|
||||
static let bundle: Bundle = {
|
||||
#if SWIFT_PACKAGE
|
||||
return Bundle.module
|
||||
#else
|
||||
return Bundle(for: BundleToken.self)
|
||||
#endif
|
||||
}()
|
||||
}
|
||||
// swiftlint:enable convenience_type
|
||||
{% endif %}
|
||||
{% elif storyboards %}
|
||||
// Mixed AppKit and UIKit storyboard files found, please invoke swiftgen with these separately
|
||||
{% else %}
|
||||
// No storyboard found
|
||||
{% endif %}
|
|
@ -0,0 +1,60 @@
|
|||
// swiftlint:disable all
|
||||
// Generated using SwiftGen — https://github.com/SwiftGen/SwiftGen
|
||||
|
||||
{% if platform and storyboards %}
|
||||
{% set accessModifier %}{% if param.publicAccess %}public{% else %}internal{% endif %}{% endset %}
|
||||
{% set isAppKit %}{% if platform == "macOS" %}true{% endif %}{% endset %}
|
||||
// swiftlint:disable sorted_imports
|
||||
import Foundation
|
||||
{% for module in modules where module != env.PRODUCT_MODULE_NAME and module != param.module %}
|
||||
import {{module}}
|
||||
{% endfor %}
|
||||
|
||||
// swiftlint:disable superfluous_disable_command
|
||||
// swiftlint:disable file_length
|
||||
|
||||
// MARK: - Storyboard Segues
|
||||
|
||||
// swiftlint:disable explicit_type_interface identifier_name line_length type_body_length type_name
|
||||
{{accessModifier}} enum {{param.enumName|default:"StoryboardSegue"}} {
|
||||
{% for storyboard in storyboards where storyboard.segues %}
|
||||
{{accessModifier}} enum {{storyboard.name|swiftIdentifier:"pretty"|escapeReservedKeywords}}: String, SegueType {
|
||||
{% for segue in storyboard.segues %}
|
||||
{% set segueID %}{{segue.identifier|swiftIdentifier:"pretty"|lowerFirstWord}}{% endset %}
|
||||
case {{segueID|escapeReservedKeywords}}{% if segueID != segue.identifier %} = "{{segue.identifier}}"{% endif %}
|
||||
{% endfor %}
|
||||
}
|
||||
{% endfor %}
|
||||
}
|
||||
// swiftlint:enable explicit_type_interface identifier_name line_length type_body_length type_name
|
||||
|
||||
// MARK: - Implementation Details
|
||||
|
||||
{{accessModifier}} protocol SegueType: RawRepresentable {}
|
||||
|
||||
{{accessModifier}} extension {% if isAppKit %}NSSeguePerforming{% else %}UIViewController{% endif %} {
|
||||
func perform<S: SegueType>(segue: S, sender: Any? = nil) where S.RawValue == String {
|
||||
let identifier = {% if isAppKit %}NSStoryboardSegue.Identifier({% endif %}segue.rawValue{% if isAppKit %}){% endif %}
|
||||
performSegue{% if isAppKit %}?{% endif %}(withIdentifier: identifier, sender: sender)
|
||||
}
|
||||
}
|
||||
|
||||
{{accessModifier}} extension SegueType where RawValue == String {
|
||||
init?(_ segue: {% if isAppKit %}NS{% else %}UI{% endif %}StoryboardSegue) {
|
||||
{% if isAppKit %}
|
||||
#if swift(>=4.2)
|
||||
guard let identifier = segue.identifier else { return nil }
|
||||
#else
|
||||
guard let identifier = segue.identifier?.rawValue else { return nil }
|
||||
#endif
|
||||
{% else %}
|
||||
guard let identifier = segue.identifier else { return nil }
|
||||
{% endif %}
|
||||
self.init(rawValue: identifier)
|
||||
}
|
||||
}
|
||||
{% elif storyboards %}
|
||||
// Mixed AppKit and UIKit storyboard files found, please invoke swiftgen with these separately
|
||||
{% else %}
|
||||
// No storyboard found
|
||||
{% endif %}
|
|
@ -0,0 +1,60 @@
|
|||
// swiftlint:disable all
|
||||
// Generated using SwiftGen — https://github.com/SwiftGen/SwiftGen
|
||||
|
||||
{% if platform and storyboards %}
|
||||
{% set accessModifier %}{% if param.publicAccess %}public{% else %}internal{% endif %}{% endset %}
|
||||
{% set isAppKit %}{% if platform == "macOS" %}true{% endif %}{% endset %}
|
||||
// swiftlint:disable sorted_imports
|
||||
import Foundation
|
||||
{% for module in modules where module != env.PRODUCT_MODULE_NAME and module != param.module %}
|
||||
import {{module}}
|
||||
{% endfor %}
|
||||
|
||||
// swiftlint:disable superfluous_disable_command
|
||||
// swiftlint:disable file_length
|
||||
|
||||
// MARK: - Storyboard Segues
|
||||
|
||||
// swiftlint:disable explicit_type_interface identifier_name line_length type_body_length type_name
|
||||
{{accessModifier}} enum {{param.enumName|default:"StoryboardSegue"}} {
|
||||
{% for storyboard in storyboards where storyboard.segues %}
|
||||
{{accessModifier}} enum {{storyboard.name|swiftIdentifier:"pretty"|escapeReservedKeywords}}: String, SegueType {
|
||||
{% for segue in storyboard.segues %}
|
||||
{% set segueID %}{{segue.identifier|swiftIdentifier:"pretty"|lowerFirstWord}}{% endset %}
|
||||
case {{segueID|escapeReservedKeywords}}{% if segueID != segue.identifier %} = "{{segue.identifier}}"{% endif %}
|
||||
{% endfor %}
|
||||
}
|
||||
{% endfor %}
|
||||
}
|
||||
// swiftlint:enable explicit_type_interface identifier_name line_length type_body_length type_name
|
||||
|
||||
// MARK: - Implementation Details
|
||||
|
||||
{{accessModifier}} protocol SegueType: RawRepresentable {}
|
||||
|
||||
{{accessModifier}} extension {% if isAppKit %}NSSeguePerforming{% else %}UIViewController{% endif %} {
|
||||
func perform<S: SegueType>(segue: S, sender: Any? = nil) where S.RawValue == String {
|
||||
let identifier = {% if isAppKit %}NSStoryboardSegue.Identifier({% endif %}segue.rawValue{% if isAppKit %}){% endif %}
|
||||
performSegue{% if isAppKit %}?{% endif %}(withIdentifier: identifier, sender: sender)
|
||||
}
|
||||
}
|
||||
|
||||
{{accessModifier}} extension SegueType where RawValue == String {
|
||||
init?(_ segue: {% if isAppKit %}NS{% else %}UI{% endif %}StoryboardSegue) {
|
||||
{% if isAppKit %}
|
||||
#if swift(>=4.2)
|
||||
guard let identifier = segue.identifier else { return nil }
|
||||
#else
|
||||
guard let identifier = segue.identifier?.rawValue else { return nil }
|
||||
#endif
|
||||
{% else %}
|
||||
guard let identifier = segue.identifier else { return nil }
|
||||
{% endif %}
|
||||
self.init(rawValue: identifier)
|
||||
}
|
||||
}
|
||||
{% elif storyboards %}
|
||||
// Mixed AppKit and UIKit storyboard files found, please invoke swiftgen with these separately
|
||||
{% else %}
|
||||
// No storyboard found
|
||||
{% endif %}
|
|
@ -0,0 +1,82 @@
|
|||
// swiftlint:disable all
|
||||
// Generated using SwiftGen — https://github.com/SwiftGen/SwiftGen
|
||||
|
||||
{% if files %}
|
||||
{% set accessModifier %}{% if param.publicAccess %}public{% else %}internal{% endif %}{% endset %}
|
||||
import Foundation
|
||||
|
||||
// swiftlint:disable superfluous_disable_command
|
||||
// swiftlint:disable file_length
|
||||
|
||||
// MARK: - JSON Files
|
||||
{% macro fileBlock file %}
|
||||
{% call documentBlock file file.document %}
|
||||
{% endmacro %}
|
||||
{% macro documentBlock file document %}
|
||||
{% set rootType %}{% call typeBlock document.metadata %}{% endset %}
|
||||
{% if document.metadata.type == "Array" %}
|
||||
{{accessModifier}} static let items: {{rootType}} = {% call valueBlock document.data document.metadata %}
|
||||
{% elif document.metadata.type == "Dictionary" %}
|
||||
{% for key,value in document.metadata.properties %}
|
||||
{{accessModifier}} {% call propertyBlock key value document.data %}
|
||||
{% endfor %}
|
||||
{% else %}
|
||||
{{accessModifier}} static let value: {{rootType}} = {% call valueBlock document.data document.metadata %}
|
||||
{% endif %}
|
||||
{% endmacro %}
|
||||
{% macro typeBlock metadata %}{% filter removeNewlines:"leading" %}
|
||||
{% if metadata.type == "Array" %}
|
||||
[{% call typeBlock metadata.element %}]
|
||||
{% elif metadata.type == "Dictionary" %}
|
||||
[String: Any]
|
||||
{% elif metadata.type == "Optional" %}
|
||||
Any?
|
||||
{% else %}
|
||||
{{metadata.type}}
|
||||
{% endif %}
|
||||
{% endfilter %}{% endmacro %}
|
||||
{% macro propertyBlock key metadata data %}{% filter removeNewlines:"leading" %}
|
||||
{% set propertyName %}{{key|swiftIdentifier:"pretty"|lowerFirstWord|escapeReservedKeywords}}{% endset %}
|
||||
{% set propertyType %}{% call typeBlock metadata %}{% endset %}
|
||||
static let {{propertyName}}: {{propertyType}} = {% call valueBlock data[key] metadata %}
|
||||
{% endfilter %}{% endmacro %}
|
||||
{% macro valueBlock value metadata %}{% filter removeNewlines:"leading" %}
|
||||
{% if metadata.type == "String" %}
|
||||
"{{ value }}"
|
||||
{% elif metadata.type == "Optional" %}
|
||||
nil
|
||||
{% elif metadata.type == "Array" and value %}
|
||||
[{% for value in value %}
|
||||
{% call valueBlock value metadata.element.items[forloop.counter0]|default:metadata.element %}
|
||||
{{ ", " if not forloop.last }}
|
||||
{% endfor %}]
|
||||
{% elif metadata.type == "Dictionary" %}
|
||||
[{% for key,value in value %}
|
||||
"{{key}}": {% call valueBlock value metadata.properties[key] %}
|
||||
{{ ", " if not forloop.last }}
|
||||
{% empty %}
|
||||
:
|
||||
{% endfor %}]
|
||||
{% elif metadata.type == "Bool" %}
|
||||
{% if value %}true{% else %}false{% endif %}
|
||||
{% else %}
|
||||
{{ value }}
|
||||
{% endif %}
|
||||
{% endfilter %}{% endmacro %}
|
||||
|
||||
// swiftlint:disable identifier_name line_length number_separator type_body_length
|
||||
{{accessModifier}} enum {{param.enumName|default:"JSONFiles"}} {
|
||||
{% if files.count > 1 or param.forceFileNameEnum %}
|
||||
{% for file in files %}
|
||||
{{accessModifier}} enum {{file.name|swiftIdentifier:"pretty"|escapeReservedKeywords}} {
|
||||
{% filter indent:2 %}{% call fileBlock file %}{% endfilter %}
|
||||
}
|
||||
{% endfor %}
|
||||
{% else %}
|
||||
{% call fileBlock files.first %}
|
||||
{% endif %}
|
||||
}
|
||||
// swiftlint:enable identifier_name line_length number_separator type_body_length
|
||||
{% else %}
|
||||
// No files found
|
||||
{% endif %}
|
|
@ -0,0 +1,82 @@
|
|||
// swiftlint:disable all
|
||||
// Generated using SwiftGen — https://github.com/SwiftGen/SwiftGen
|
||||
|
||||
{% if files %}
|
||||
{% set accessModifier %}{% if param.publicAccess %}public{% else %}internal{% endif %}{% endset %}
|
||||
import Foundation
|
||||
|
||||
// swiftlint:disable superfluous_disable_command
|
||||
// swiftlint:disable file_length
|
||||
|
||||
// MARK: - JSON Files
|
||||
{% macro fileBlock file %}
|
||||
{% call documentBlock file file.document %}
|
||||
{% endmacro %}
|
||||
{% macro documentBlock file document %}
|
||||
{% set rootType %}{% call typeBlock document.metadata %}{% endset %}
|
||||
{% if document.metadata.type == "Array" %}
|
||||
{{accessModifier}} static let items: {{rootType}} = {% call valueBlock document.data document.metadata %}
|
||||
{% elif document.metadata.type == "Dictionary" %}
|
||||
{% for key,value in document.metadata.properties %}
|
||||
{{accessModifier}} {% call propertyBlock key value document.data %}
|
||||
{% endfor %}
|
||||
{% else %}
|
||||
{{accessModifier}} static let value: {{rootType}} = {% call valueBlock document.data document.metadata %}
|
||||
{% endif %}
|
||||
{% endmacro %}
|
||||
{% macro typeBlock metadata %}{% filter removeNewlines:"leading" %}
|
||||
{% if metadata.type == "Array" %}
|
||||
[{% call typeBlock metadata.element %}]
|
||||
{% elif metadata.type == "Dictionary" %}
|
||||
[String: Any]
|
||||
{% elif metadata.type == "Optional" %}
|
||||
Any?
|
||||
{% else %}
|
||||
{{metadata.type}}
|
||||
{% endif %}
|
||||
{% endfilter %}{% endmacro %}
|
||||
{% macro propertyBlock key metadata data %}{% filter removeNewlines:"leading" %}
|
||||
{% set propertyName %}{{key|swiftIdentifier:"pretty"|lowerFirstWord|escapeReservedKeywords}}{% endset %}
|
||||
{% set propertyType %}{% call typeBlock metadata %}{% endset %}
|
||||
static let {{propertyName}}: {{propertyType}} = {% call valueBlock data[key] metadata %}
|
||||
{% endfilter %}{% endmacro %}
|
||||
{% macro valueBlock value metadata %}{% filter removeNewlines:"leading" %}
|
||||
{% if metadata.type == "String" %}
|
||||
"{{ value }}"
|
||||
{% elif metadata.type == "Optional" %}
|
||||
nil
|
||||
{% elif metadata.type == "Array" and value %}
|
||||
[{% for value in value %}
|
||||
{% call valueBlock value metadata.element.items[forloop.counter0]|default:metadata.element %}
|
||||
{{ ", " if not forloop.last }}
|
||||
{% endfor %}]
|
||||
{% elif metadata.type == "Dictionary" %}
|
||||
[{% for key,value in value %}
|
||||
"{{key}}": {% call valueBlock value metadata.properties[key] %}
|
||||
{{ ", " if not forloop.last }}
|
||||
{% empty %}
|
||||
:
|
||||
{% endfor %}]
|
||||
{% elif metadata.type == "Bool" %}
|
||||
{% if value %}true{% else %}false{% endif %}
|
||||
{% else %}
|
||||
{{ value }}
|
||||
{% endif %}
|
||||
{% endfilter %}{% endmacro %}
|
||||
|
||||
// swiftlint:disable identifier_name line_length number_separator type_body_length
|
||||
{{accessModifier}} enum {{param.enumName|default:"JSONFiles"}} {
|
||||
{% if files.count > 1 or param.forceFileNameEnum %}
|
||||
{% for file in files %}
|
||||
{{accessModifier}} enum {{file.name|swiftIdentifier:"pretty"|escapeReservedKeywords}} {
|
||||
{% filter indent:2 %}{% call fileBlock file %}{% endfilter %}
|
||||
}
|
||||
{% endfor %}
|
||||
{% else %}
|
||||
{% call fileBlock files.first %}
|
||||
{% endif %}
|
||||
}
|
||||
// swiftlint:enable identifier_name line_length number_separator type_body_length
|
||||
{% else %}
|
||||
// No files found
|
||||
{% endif %}
|
|
@ -0,0 +1,112 @@
|
|||
// swiftlint:disable all
|
||||
// Generated using SwiftGen — https://github.com/SwiftGen/SwiftGen
|
||||
|
||||
{% if files %}
|
||||
{% set accessModifier %}{% if param.publicAccess %}public{% else %}internal{% endif %}{% endset %}
|
||||
import Foundation
|
||||
|
||||
// swiftlint:disable superfluous_disable_command
|
||||
// swiftlint:disable file_length
|
||||
|
||||
// MARK: - JSON Files
|
||||
{% macro fileBlock file %}
|
||||
{% call documentBlock file file.document %}
|
||||
{% endmacro %}
|
||||
{% macro documentBlock file document %}
|
||||
{% set rootType %}{% call typeBlock document.metadata %}{% endset %}
|
||||
{% if document.metadata.type == "Array" %}
|
||||
{{accessModifier}} static let items: {{rootType}} = objectFromJSON(at: "{% call transformPath file.path %}")
|
||||
{% elif document.metadata.type == "Dictionary" %}
|
||||
private static let _document = JSONDocument(path: "{% call transformPath file.path %}")
|
||||
|
||||
{% for key,value in document.metadata.properties %}
|
||||
{{accessModifier}} {% call propertyBlock key value %}
|
||||
{% endfor %}
|
||||
{% else %}
|
||||
{{accessModifier}} static let value: {{rootType}} = objectFromJSON(at: "{% call transformPath file.path %}")
|
||||
{% endif %}
|
||||
{% endmacro %}
|
||||
{% macro typeBlock metadata %}{% filter removeNewlines:"leading" %}
|
||||
{% if metadata.type == "Array" %}
|
||||
[{% call typeBlock metadata.element %}]
|
||||
{% elif metadata.type == "Dictionary" %}
|
||||
[String: Any]
|
||||
{% elif metadata.type == "Optional" %}
|
||||
Any?
|
||||
{% else %}
|
||||
{{metadata.type}}
|
||||
{% endif %}
|
||||
{% endfilter %}{% endmacro %}
|
||||
{% macro propertyBlock key metadata %}{% filter removeNewlines:"leading" %}
|
||||
{% set propertyName %}{{key|swiftIdentifier:"pretty"|lowerFirstWord|escapeReservedKeywords}}{% endset %}
|
||||
{% set propertyType %}{% call typeBlock metadata %}{% endset %}
|
||||
static let {{propertyName}}: {{propertyType}} = _document["{{key}}"]
|
||||
{% endfilter %}{% endmacro %}
|
||||
{% macro transformPath path %}{% filter removeNewlines %}
|
||||
{% if param.preservePath %}
|
||||
{{path}}
|
||||
{% else %}
|
||||
{{path|basename}}
|
||||
{% endif %}
|
||||
{% endfilter %}{% endmacro %}
|
||||
|
||||
// swiftlint:disable identifier_name line_length type_body_length
|
||||
{{accessModifier}} enum {{param.enumName|default:"JSONFiles"}} {
|
||||
{% if files.count > 1 or param.forceFileNameEnum %}
|
||||
{% for file in files %}
|
||||
{{accessModifier}} enum {{file.name|swiftIdentifier:"pretty"|escapeReservedKeywords}} {
|
||||
{% filter indent:2 %}{% call fileBlock file %}{% endfilter %}
|
||||
}
|
||||
{% endfor %}
|
||||
{% else %}
|
||||
{% call fileBlock files.first %}
|
||||
{% endif %}
|
||||
}
|
||||
// swiftlint:enable identifier_name line_length type_body_length
|
||||
|
||||
// MARK: - Implementation Details
|
||||
|
||||
private func objectFromJSON<T>(at path: String) -> T {
|
||||
{% if param.lookupFunction %}
|
||||
guard let url = {{param.lookupFunction}}(path),
|
||||
{% else %}
|
||||
guard let url = {{param.bundle|default:"BundleToken.bundle"}}.url(forResource: path, withExtension: nil),
|
||||
{% endif %}
|
||||
let json = try? JSONSerialization.jsonObject(with: Data(contentsOf: url), options: []),
|
||||
let result = json as? T else {
|
||||
fatalError("Unable to load JSON at path: \(path)")
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
private struct JSONDocument {
|
||||
let data: [String: Any]
|
||||
|
||||
init(path: String) {
|
||||
self.data = objectFromJSON(at: path)
|
||||
}
|
||||
|
||||
subscript<T>(key: String) -> T {
|
||||
guard let result = data[key] as? T else {
|
||||
fatalError("Property '\(key)' is not of type \(T.self)")
|
||||
}
|
||||
return result
|
||||
}
|
||||
}
|
||||
{% if not param.bundle and not param.lookupFunction %}
|
||||
|
||||
// swiftlint:disable convenience_type
|
||||
private final class BundleToken {
|
||||
static let bundle: Bundle = {
|
||||
#if SWIFT_PACKAGE
|
||||
return Bundle.module
|
||||
#else
|
||||
return Bundle(for: BundleToken.self)
|
||||
#endif
|
||||
}()
|
||||
}
|
||||
// swiftlint:enable convenience_type
|
||||
{% endif %}
|
||||
{% else %}
|
||||
// No files found
|
||||
{% endif %}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue