mirror of
https://github.com/Ranchero-Software/NetNewsWire.git
synced 2024-12-23 16:20:53 +01:00
Implement initial alert dialog when importing a theme
This commit is contained in:
parent
0d089a7246
commit
98b9080b1f
@ -319,6 +319,12 @@ class AppDelegate: NSObject, NSApplicationDelegate, NSUserInterfaceValidations,
|
||||
AccountManager.shared.receiveRemoteNotification(userInfo: userInfo)
|
||||
}
|
||||
|
||||
func application(_ sender: NSApplication, openFile filename: String) -> Bool {
|
||||
guard filename.hasSuffix(".nnwtheme") else { return false }
|
||||
importTheme(filename: filename)
|
||||
return true
|
||||
}
|
||||
|
||||
func applicationWillTerminate(_ notification: Notification) {
|
||||
shuttingDown = true
|
||||
saveState()
|
||||
@ -769,7 +775,6 @@ private extension AppDelegate {
|
||||
}
|
||||
|
||||
func objectsForInspector() -> [Any]? {
|
||||
|
||||
guard let window = NSApplication.shared.mainWindow, let windowController = window.windowController as? MainWindowController else {
|
||||
return nil
|
||||
}
|
||||
@ -782,7 +787,6 @@ private extension AppDelegate {
|
||||
}
|
||||
|
||||
func updateSortMenuItems() {
|
||||
|
||||
let sortByNewestOnTop = AppDefaults.shared.timelineSortDirection == .orderedDescending
|
||||
sortByNewestArticleOnTopMenuItem.state = sortByNewestOnTop ? .on : .off
|
||||
sortByOldestArticleOnTopMenuItem.state = sortByNewestOnTop ? .off : .on
|
||||
@ -792,6 +796,48 @@ private extension AppDelegate {
|
||||
let groupByFeedEnabled = AppDefaults.shared.timelineGroupByFeed
|
||||
groupArticlesByFeedMenuItem.state = groupByFeedEnabled ? .on : .off
|
||||
}
|
||||
|
||||
func importTheme(filename: String) {
|
||||
guard let window = mainWindowController?.window else { return }
|
||||
|
||||
let theme = ArticleTheme(path: filename)
|
||||
|
||||
let alert = NSAlert()
|
||||
alert.alertStyle = .informational
|
||||
|
||||
let localizedMessageText = NSLocalizedString("Install “%@” by %@?", comment: "Theme message text")
|
||||
alert.messageText = NSString.localizedStringWithFormat(localizedMessageText as NSString, theme.name, theme.creatorName) as String
|
||||
|
||||
var attrs = [NSAttributedString.Key : Any]()
|
||||
attrs[.font] = NSFont.systemFont(ofSize: NSFont.smallSystemFontSize)
|
||||
attrs[.foregroundColor] = NSColor.textColor
|
||||
|
||||
let titleParagraphStyle = NSMutableParagraphStyle()
|
||||
titleParagraphStyle.alignment = .center
|
||||
attrs[.paragraphStyle] = titleParagraphStyle
|
||||
|
||||
let websiteText = NSMutableAttributedString()
|
||||
websiteText.append(NSAttributedString(string: NSLocalizedString("Author's Website", comment: "Author's Website"), attributes: attrs))
|
||||
websiteText.append(NSAttributedString(string: "\n"))
|
||||
|
||||
attrs[.link] = theme.creatorHomePage
|
||||
websiteText.append(NSAttributedString(string: theme.creatorHomePage, attributes: attrs))
|
||||
|
||||
let textView = NSTextView(frame: CGRect(x: 0, y: 0, width: 200, height: 15))
|
||||
textView.isEditable = false
|
||||
textView.drawsBackground = false
|
||||
textView.textStorage?.setAttributedString(websiteText)
|
||||
alert.accessoryView = textView
|
||||
|
||||
alert.addButton(withTitle: NSLocalizedString("Install Style", comment: "Install Style"))
|
||||
alert.addButton(withTitle: NSLocalizedString("Cancel", comment: "Cancel Install Style"))
|
||||
|
||||
alert.beginSheetModal(for: window) { [weak self] result in
|
||||
if result == NSApplication.ModalResponse.alertFirstButtonReturn {
|
||||
guard let self = self else { return }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -11,10 +11,33 @@ import Foundation
|
||||
struct ArticleTheme: Equatable {
|
||||
|
||||
static let defaultTheme = ArticleTheme()
|
||||
static let nnwThemeSuffix = ".nnwtheme"
|
||||
|
||||
private static let defaultThemeName = NSLocalizedString("Default", comment: "Default")
|
||||
private static let unknownValue = NSLocalizedString("Unknown", comment: "Unknown Value")
|
||||
|
||||
let path: String?
|
||||
let template: String?
|
||||
let css: String?
|
||||
let info: NSDictionary?
|
||||
|
||||
var name: String {
|
||||
guard let path = path else { return Self.defaultThemeName }
|
||||
return Self.themeNameForPath(path)
|
||||
}
|
||||
|
||||
var creatorHomePage: String {
|
||||
return info?["CreatorHomePage"] as? String ?? Self.unknownValue
|
||||
}
|
||||
|
||||
var creatorName: String {
|
||||
return info?["CreatorName"] as? String ?? Self.unknownValue
|
||||
}
|
||||
|
||||
var version: String {
|
||||
return info?["Version"] as? String ?? "0.0"
|
||||
}
|
||||
|
||||
private let info: NSDictionary?
|
||||
|
||||
init() {
|
||||
self.path = nil;
|
||||
@ -23,14 +46,14 @@ struct ArticleTheme: Equatable {
|
||||
let sharedCSSPath = Bundle.main.path(forResource: "shared", ofType: "css")!
|
||||
let platformCSSPath = Bundle.main.path(forResource: "styleSheet", ofType: "css")!
|
||||
|
||||
if let sharedCSS = stringAtPath(sharedCSSPath), let platformCSS = stringAtPath(platformCSSPath) {
|
||||
if let sharedCSS = Self.stringAtPath(sharedCSSPath), let platformCSS = Self.stringAtPath(platformCSSPath) {
|
||||
css = sharedCSS + "\n" + platformCSS
|
||||
} else {
|
||||
css = nil
|
||||
}
|
||||
|
||||
let templatePath = Bundle.main.path(forResource: "template", ofType: "html")!
|
||||
template = stringAtPath(templatePath)
|
||||
template = Self.stringAtPath(templatePath)
|
||||
}
|
||||
|
||||
init(path: String) {
|
||||
@ -41,26 +64,40 @@ struct ArticleTheme: Equatable {
|
||||
self.info = NSDictionary(contentsOfFile: infoPath)
|
||||
|
||||
let cssPath = (path as NSString).appendingPathComponent("stylesheet.css")
|
||||
self.css = stringAtPath(cssPath)
|
||||
self.css = Self.stringAtPath(cssPath)
|
||||
|
||||
let templatePath = (path as NSString).appendingPathComponent("template.html")
|
||||
self.template = stringAtPath(templatePath)
|
||||
self.template = Self.stringAtPath(templatePath)
|
||||
} else {
|
||||
self.css = stringAtPath(path)
|
||||
self.css = Self.stringAtPath(path)
|
||||
self.template = nil
|
||||
self.info = nil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static func stringAtPath(_ f: String) -> String? {
|
||||
if !FileManager.default.fileExists(atPath: f) {
|
||||
return nil
|
||||
}
|
||||
|
||||
private func stringAtPath(_ f: String) -> String? {
|
||||
|
||||
if !FileManager.default.fileExists(atPath: f) {
|
||||
if let s = try? NSString(contentsOfFile: f, usedEncoding: nil) as String {
|
||||
return s
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
if let s = try? NSString(contentsOfFile: f, usedEncoding: nil) as String {
|
||||
return s
|
||||
static func filenameWithThemeSuffixRemoved(_ filename: String) -> String {
|
||||
return filename.stripping(suffix: Self.nnwThemeSuffix)
|
||||
}
|
||||
return nil
|
||||
|
||||
static func themeNameForPath(_ f: String) -> String {
|
||||
let filename = (f as NSString).lastPathComponent
|
||||
return filenameWithThemeSuffixRemoved(filename)
|
||||
}
|
||||
|
||||
static func pathIsPathForThemeName(_ themeName: String, path: String) -> Bool {
|
||||
let filename = (path as NSString).lastPathComponent
|
||||
return filenameWithThemeSuffixRemoved(filename) == themeName
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -17,9 +17,6 @@ import RSCore
|
||||
let ArticleThemeNamesDidChangeNotification = "ArticleThemeNamesDidChangeNotification"
|
||||
let CurrentArticleThemeDidChangeNotification = "CurrentArticleThemeDidChangeNotification"
|
||||
|
||||
private let themesInResourcesFolderName = "Themes"
|
||||
private let nnwThemeSuffix = ".nnwtheme"
|
||||
|
||||
final class ArticleThemesManager {
|
||||
|
||||
static var shared: ArticleThemesManager!
|
||||
@ -80,7 +77,7 @@ final class ArticleThemesManager {
|
||||
// MARK : Internal
|
||||
|
||||
private func updateThemeNames() {
|
||||
let updatedThemeNames = allThemePaths(folderPath).map { themeNameForPath($0) }
|
||||
let updatedThemeNames = allThemePaths(folderPath).map { ArticleTheme.themeNameForPath($0) }
|
||||
|
||||
if updatedThemeNames != themeNames {
|
||||
themeNames = updatedThemeNames
|
||||
@ -104,7 +101,6 @@ final class ArticleThemesManager {
|
||||
}
|
||||
|
||||
private func updateCurrentTheme() {
|
||||
|
||||
var themeName = currentThemeName
|
||||
if !themeNames.contains(themeName) {
|
||||
themeName = AppDefaults.defaultThemeName
|
||||
@ -121,33 +117,19 @@ final class ArticleThemesManager {
|
||||
currentTheme = articleTheme
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private func allThemePaths(_ folder: String) -> [String] {
|
||||
let filepaths = FileManager.default.filePaths(inFolder: folder)
|
||||
return filepaths?.filter { $0.hasSuffix(nnwThemeSuffix) } ?? []
|
||||
}
|
||||
|
||||
private func filenameWithThemeSuffixRemoved(_ filename: String) -> String {
|
||||
return filename.stripping(suffix: nnwThemeSuffix)
|
||||
}
|
||||
|
||||
private func themeNameForPath(_ f: String) -> String {
|
||||
let filename = (f as NSString).lastPathComponent
|
||||
return filenameWithThemeSuffixRemoved(filename)
|
||||
}
|
||||
|
||||
private func pathIsPathForThemeName(_ themeName: String, path: String) -> Bool {
|
||||
let filename = (path as NSString).lastPathComponent
|
||||
return filenameWithThemeSuffixRemoved(filename) == themeName
|
||||
}
|
||||
|
||||
private func pathForThemeName(_ themeName: String, folder: String) -> String? {
|
||||
for onePath in allThemePaths(folder) {
|
||||
if pathIsPathForThemeName(themeName, path: onePath) {
|
||||
return onePath
|
||||
}
|
||||
private func allThemePaths(_ folder: String) -> [String] {
|
||||
let filepaths = FileManager.default.filePaths(inFolder: folder)
|
||||
return filepaths?.filter { $0.hasSuffix(ArticleTheme.nnwThemeSuffix) } ?? []
|
||||
}
|
||||
return nil
|
||||
|
||||
private func pathForThemeName(_ themeName: String, folder: String) -> String? {
|
||||
for onePath in allThemePaths(folder) {
|
||||
if ArticleTheme.pathIsPathForThemeName(themeName, path: onePath) {
|
||||
return onePath
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user