Skip to content

Commit 2662c77

Browse files
committed
Merge branch 'release/v0.12.0'
2 parents 586c339 + dada4b3 commit 2662c77

File tree

12 files changed

+235
-16
lines changed

12 files changed

+235
-16
lines changed

uPic/Base.lproj/Main.storyboard

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,9 +104,11 @@
104104
<outlet property="cancelUploadMenuSeparator" destination="ggN-TB-JZW" id="V4H-J4-ftj"/>
105105
<outlet property="checkUpdateMenuItem" destination="yai-4F-Btp" id="klG-hy-GGO"/>
106106
<outlet property="compressFactorMenuItem" destination="eIU-EA-uQZ" id="uMq-Nm-vXy"/>
107+
<outlet property="exportHostsMenuItem" destination="Yuc-Vp-9Pd" id="JIW-vZ-WbR"/>
107108
<outlet property="helpMenuItem" destination="2Jw-ET-3eH" id="Ubq-wz-L3N"/>
108109
<outlet property="historyMenuItem" destination="EhO-Zw-XXj" id="okQ-0q-kK5"/>
109110
<outlet property="hostMenuItem" destination="d02-bT-1Lv" id="Ah0-J0-Z4M"/>
111+
<outlet property="importHostsMenuItem" destination="HNM-7K-zzn" id="Jmj-DT-7ky"/>
110112
<outlet property="ouputFormatMenuItem" destination="1BX-LF-q51" id="H54-M9-CBq"/>
111113
<outlet property="preferenceMenuItem" destination="VW7-Z2-hXR" id="Mhm-Tb-F4W"/>
112114
<outlet property="quitMenuItem" destination="0JF-m2-1iq" id="qTr-PH-bBg"/>
@@ -213,6 +215,18 @@
213215
<action selector="guideMenuItemClicked:" target="veO-oa-UPB" id="PRm-Bb-SKG"/>
214216
</connections>
215217
</menuItem>
218+
<menuItem title="导入图床配置" id="HNM-7K-zzn">
219+
<modifierMask key="keyEquivalentModifierMask"/>
220+
<connections>
221+
<action selector="importHostsMenuItemClicked:" target="veO-oa-UPB" id="76m-Ru-6rH"/>
222+
</connections>
223+
</menuItem>
224+
<menuItem title="导出图床配置" id="Yuc-Vp-9Pd">
225+
<modifierMask key="keyEquivalentModifierMask"/>
226+
<connections>
227+
<action selector="exportHostsMenuItemClicked:" target="veO-oa-UPB" id="ZAp-pp-wFi"/>
228+
</connections>
229+
</menuItem>
216230
</items>
217231
</menu>
218232
</menuItem>

uPic/Extensions/NotificationExt.swift

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,27 @@ class NotificationExt:NSObject {
4545
self.post(title: NSLocalizedString("notification.upload.task-not-complete.subtitle", comment: ""),
4646
info: body!)
4747
}
48+
49+
50+
func postImportErrorNotice(_ body: String? = NSLocalizedString("notification.import.error.body", comment: "")) {
51+
self.post(title: NSLocalizedString("notification.import.error.title", comment: ""),
52+
info: body!)
53+
}
54+
55+
func postImportSuccessfulNotice() {
56+
self.post(title: NSLocalizedString("notification.success.title", comment: ""),
57+
info: NSLocalizedString("notification.import.success.body", comment: ""))
58+
}
59+
60+
func postExportErrorNotice(_ body: String? = NSLocalizedString("notification.export.error.body.invalid", comment: "")) {
61+
self.post(title: NSLocalizedString("notification.upload.task-not-complete.subtitle", comment: ""),
62+
info: body!)
63+
}
64+
65+
func postExportSuccessfulNotice() {
66+
self.post(title: NSLocalizedString("notification.success.title", comment: ""),
67+
info: NSLocalizedString("notification.export.success.body", comment: ""))
68+
}
4869
}
4970

5071
@available(OSX 10.14, *)

uPic/General/Managers/ConfigManager.swift

Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -148,3 +148,108 @@ extension ConfigManager {
148148
}
149149
}
150150

151+
extension ConfigManager {
152+
// import & export config
153+
154+
func importHosts() {
155+
NSApp.activate(ignoringOtherApps: true)
156+
let openPanel = NSOpenPanel()
157+
openPanel.allowsMultipleSelection = false
158+
openPanel.canChooseDirectories = false
159+
openPanel.canCreateDirectories = false
160+
openPanel.allowedFileTypes = ["json"]
161+
162+
openPanel.begin { (result) -> Void in
163+
if result.rawValue == NSApplication.ModalResponse.OK.rawValue {
164+
guard let url = openPanel.url,
165+
let data = NSData(contentsOfFile: url.path),
166+
let array = try? JSONSerialization.jsonObject(with: data as Data) as? [String]
167+
else {
168+
NotificationExt.shared.postImportErrorNotice()
169+
return
170+
}
171+
let hostItems = array.map(){ str in
172+
return Host.deserialize(str: str)
173+
}.filter { $0 != nil }
174+
if hostItems.count == 0 {
175+
NotificationExt.shared.postImportErrorNotice()
176+
return
177+
}
178+
179+
// choose import method
180+
181+
let alert = NSAlert()
182+
183+
alert.messageText = NSLocalizedString("alert.import_hosts_title", comment: "")
184+
alert.informativeText = NSLocalizedString("alert.import_hosts_description", comment: "")
185+
186+
alert.addButton(withTitle: NSLocalizedString("alert.import_hosts_merge", comment: "")).refusesFirstResponder = true
187+
188+
alert.addButton(withTitle: NSLocalizedString("alert.import_hosts_overwrite", comment: "")).refusesFirstResponder = true
189+
190+
let modalResult = alert.runModal()
191+
192+
switch modalResult {
193+
case .alertFirstButtonReturn:
194+
// current Items
195+
var currentHostItems = ConfigManager.shared.getHostItems()
196+
for host in hostItems {
197+
let isContains = currentHostItems.contains(where: {item in
198+
return item == host
199+
})
200+
if (!isContains) {
201+
currentHostItems.append(host!)
202+
}
203+
}
204+
ConfigManager.shared.setHostItems(items: currentHostItems)
205+
NotificationExt.shared.postImportSuccessfulNotice()
206+
case .alertSecondButtonReturn:
207+
ConfigManager.shared.setHostItems(items: hostItems as! [Host])
208+
NotificationExt.shared.postImportSuccessfulNotice()
209+
default:
210+
print("Cancel Import")
211+
}
212+
}
213+
}
214+
}
215+
216+
func exportHosts() {
217+
let hostItems = ConfigManager.shared.getHostItems()
218+
if hostItems.count == 0 {
219+
NotificationExt.shared.postExportErrorNotice(NSLocalizedString("notification.export.error.body.no-hosts", comment: ""))
220+
return
221+
}
222+
223+
NSApp.activate(ignoringOtherApps: true)
224+
let savePanel = NSSavePanel()
225+
savePanel.directoryURL = URL(fileURLWithPath: NSHomeDirectory().appendingPathComponent(path: "Documents"))
226+
savePanel.nameFieldStringValue = "uPic_hosts.json"
227+
savePanel.allowsOtherFileTypes = false
228+
savePanel.isExtensionHidden = true
229+
savePanel.canCreateDirectories = true
230+
savePanel.allowedFileTypes = ["json"]
231+
232+
savePanel.begin { (result) -> Void in
233+
if result.rawValue == NSApplication.ModalResponse.OK.rawValue {
234+
235+
guard let url = savePanel.url else {
236+
NotificationExt.shared.postImportErrorNotice()
237+
return
238+
}
239+
240+
let hostStrArr = hostItems.map(){ hostItem in
241+
return hostItem.serialize()
242+
}
243+
if (!JSONSerialization.isValidJSONObject(hostStrArr)) {
244+
NotificationExt.shared.postImportErrorNotice()
245+
return
246+
}
247+
let os = OutputStream(toFileAtPath: url.path, append: false)
248+
os?.open()
249+
JSONSerialization.writeJSONObject(hostStrArr, to: os!, options: .prettyPrinted, error: .none)
250+
os?.close()
251+
NotificationExt.shared.postExportSuccessfulNotice()
252+
}
253+
}
254+
}
255+
}

uPic/General/Utils/PreferenceKey.swift

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,9 @@ extension UserDefaults {
8787
for item in arr {
8888
let str = item as! String
8989
let host = Host.deserialize(str: str)
90-
result.append(host)
90+
if host != nil {
91+
result.append(host!)
92+
}
9193
}
9294
}
9395
return result

uPic/Models/Host.swift

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -60,15 +60,15 @@ class Host: Equatable, CustomDebugStringConvertible, Codable {
6060
}
6161

6262
func copy() -> Host {
63-
let newHost = Host.deserialize(str: self.serialize())
63+
let newHost = Host.deserialize(str: self.serialize())!
6464
newHost.id = Date().timeStamp
6565
return newHost
6666
}
6767

68-
static func deserialize(str: String) -> Host {
69-
let data = str.data(using: String.Encoding.utf8)!
70-
let json = try! JSON(data: data)
71-
let type = HostType(rawValue: json["type"].intValue)!
68+
static func deserialize(str: String) -> Host? {
69+
guard let data = str.data(using: String.Encoding.utf8), let json = try? JSON(data: data),let type = HostType(rawValue: json["type"].intValue) else {
70+
return nil
71+
}
7272
let hostData = HostConfig.deserialize(type: type, str: json["data"].string)
7373

7474
let host = Host(type, data: hostData)

uPic/PreferencesWindow/Base.lproj/Preferences.storyboard

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1187,7 +1187,7 @@ Gw
11871187
<image name="NSAdvanced" width="32" height="32"/>
11881188
<image name="NSPreferencesGeneral" width="32" height="32"/>
11891189
<image name="NSRemoveTemplate" width="11" height="11"/>
1190-
<image name="about" width="256" height="256"/>
1190+
<image name="about" width="1024" height="1024"/>
11911191
<image name="host" width="64" height="64"/>
11921192
</resources>
11931193
</document>

uPic/PreferencesWindow/HostPreferencesViewController.swift

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -67,19 +67,18 @@ class HostPreferencesViewController: PreferencesViewController {
6767
}
6868
}
6969

70-
7170
override func viewDidAppear() {
7271
super.viewDidAppear()
7372
self.view.window?.delegate = self
7473

7574
self.refreshButtonStatus()
75+
self.initHostItems()
7676
self.addObserver()
7777
}
7878

7979
override func viewDidDisappear() {
8080
super.viewDidDisappear()
8181
self.removeObserver()
82-
8382
}
8483

8584
@IBAction func addHostButtonClicked(_ sender: NSPopUpButton) {
@@ -154,6 +153,23 @@ class HostPreferencesViewController: PreferencesViewController {
154153

155154
// MARK: 将正在编辑的输入框执行 endEdit
156155
func blurEditingTextField() {
156+
for view in self.tableView.subviews {
157+
if !(view is NSTableRowView) {
158+
continue
159+
}
160+
for subView in view.subviews {
161+
if !(subView is NSTableCellView) {
162+
continue
163+
}
164+
let sV = subView as! NSTableCellView
165+
if let subTextField = sV.textField, let editor = subTextField.currentEditor() {
166+
subTextField.endEditing(editor)
167+
}
168+
169+
}
170+
}
171+
172+
157173
for view in self.configView.subviews {
158174
for subView in view.subviews {
159175
if !(subView is NSTextField) {
@@ -291,6 +307,7 @@ class HostPreferencesViewController: PreferencesViewController {
291307
@objc func hostConfigChanged() {
292308
hostConfigChangedDebouncedFunc(false)
293309
}
310+
294311

295312
func addObserver() {
296313
// 设置监听配置变化的节流函数,当0.5秒后没有再次变化就刷新当前状态
@@ -369,7 +386,6 @@ extension HostPreferencesViewController: NSTextFieldDelegate {
369386
}
370387

371388
extension HostPreferencesViewController: NSWindowDelegate {
372-
373389
func windowShouldClose(_ sender: NSWindow) -> Bool {
374390
if self.hostItemsChanged, let window = self.view.window {
375391
let alert = NSAlert()

uPic/PreferencesWindow/PreferencesWindowController.swift

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,11 @@ class PreferencesWindowController: NSWindowController {
1717

1818
}
1919
extension PreferencesWindowController: NSWindowDelegate {
20+
21+
func windowWillBeginSheet(_ notification: Notification) {
22+
print("ssss")
23+
}
24+
2025
func windowWillClose(_ notification: Notification) {
2126
// 关闭偏好设置时在去掉 Dock 栏显示应用图标
2227
NSApp.setActivationPolicy(.accessory)

uPic/Supporting Files/Info.plist

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
<key>CFBundlePackageType</key>
2020
<string>APPL</string>
2121
<key>CFBundleShortVersionString</key>
22-
<string>0.11.2</string>
22+
<string>0.12.0</string>
2323
<key>CFBundleURLTypes</key>
2424
<array>
2525
<dict>
@@ -32,7 +32,7 @@
3232
</dict>
3333
</array>
3434
<key>CFBundleVersion</key>
35-
<string>20190901</string>
35+
<string>20190906</string>
3636
<key>LSApplicationCategoryType</key>
3737
<string>public.app-category.utilities</string>
3838
<key>LSMinimumSystemVersion</key>

uPic/Views/StatusMenuController.swift

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,9 @@ class StatusMenuController: NSObject, NSMenuDelegate {
2828
@IBOutlet weak var helpMenuItem: NSMenuItem!
2929
@IBOutlet weak var checkUpdateMenuItem: NSMenuItem!
3030
@IBOutlet weak var tutorialMenuItem: NSMenuItem!
31+
@IBOutlet weak var importHostsMenuItem: NSMenuItem!
32+
@IBOutlet weak var exportHostsMenuItem: NSMenuItem!
33+
3134
@IBOutlet weak var sponsorMenuItem: NSMenuItem!
3235
@IBOutlet weak var quitMenuItem: NSMenuItem!
3336

@@ -47,6 +50,8 @@ class StatusMenuController: NSObject, NSMenuDelegate {
4750
helpMenuItem.title = NSLocalizedString("status-menu.help", comment: "help")
4851
checkUpdateMenuItem.title = NSLocalizedString("status-menu.check-update", comment: "Check update")
4952
tutorialMenuItem.title = NSLocalizedString("status-menu.tutorial", comment: "Tutorial")
53+
importHostsMenuItem.title = NSLocalizedString("status-menu.import-hosts", comment: "")
54+
exportHostsMenuItem.title = NSLocalizedString("status-menu.export-hosts", comment: "")
5055
sponsorMenuItem.title = NSLocalizedString("status-menu.sponsor", comment: "Sponsor")
5156
quitMenuItem.title = NSLocalizedString("status-menu.quit", comment: "Quit")
5257

@@ -111,7 +116,18 @@ class StatusMenuController: NSObject, NSMenuDelegate {
111116
}
112117
NSWorkspace.shared.open(url)
113118
}
114-
119+
120+
// import hosts from config file
121+
@IBAction func importHostsMenuItemClicked(_ sender: NSMenuItem) {
122+
ConfigManager.shared.importHosts()
123+
}
124+
125+
// export hosts to config file
126+
@IBAction func exportHostsMenuItemClicked(_ sender: NSMenuItem) {
127+
ConfigManager.shared.exportHosts()
128+
}
129+
130+
115131
// support -- paypal
116132
@IBAction func paypalMenuItemClicked(_ sender: Any) {
117133
(NSApplication.shared.delegate as? AppDelegate)?.sponsorByPaypal()

uPic/en.lproj/Localizable.strings

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,22 @@
2323
/* 当前上传任务还未完成通知副标题 */
2424
"notification.upload.task-not-complete.subtitle" = "The current upload task is not complete";
2525
/* 上传失败通知标题 */
26-
"notification.upload.error.title" = "Uploaded fail";
27-
26+
"notification.upload.error.title" = "Upload failed";
27+
28+
/* 导入图床配置失败标题 */
29+
"notification.import.error.title" = "Import failed";
30+
/* 导入图床配置失败内容 */
31+
"notification.import.error.body" = "The configuration file is invalid, please check!";
32+
/* 导入图床配置成功内容 */
33+
"notification.import.success.body" = "The configuration has been imported, please check and use!";
34+
/* 导出图床配置失败标题 */
35+
"notification.export.error.title" = "Export failed";
36+
/* 导出图床配置失败内容 */
37+
"notification.export.error.body.no-hosts" = "No exportable hosts!";
38+
/* 导出图床配置失败内容2 */
39+
"notification.export.error.body.invalid" = "configuration export error!";
40+
/* 导出图床配置成功内容 */
41+
"notification.export.success.body" = "The configuration file is exported successfully, Do not modify the file contents!";
2842

2943
/* 文件不存在或已被删除 */
3044
"file-does-not-exist" = "The file does not exist or has been deleted!";
@@ -69,14 +83,19 @@
6983
/* 菜单栏帮助 */
7084
"status-menu.help" = "Help";
7185
"status-menu.tutorial" = "Tutorial";
86+
"status-menu.import-hosts" = "Import hosts";
87+
"status-menu.export-hosts" = "Export hosts";
7288
"status-menu.sponsor" = "Sponsor";
7389
/* cancel upload */
7490
"status-menu.cancel-upload" = "Cancel upload";
7591

7692
"alert.reset_preferences_title" = "Reset User Preferences?";
7793
"alert.reset_preferences_description" = "⚠️ Note that this will reset all user preferences";
7894
"alert.unsave_description" = "Continuing will lose unsaved data. Do you want to continue?";
79-
95+
"alert.import_hosts_title" = "Import host configuration";
96+
"alert.import_hosts_description" = "⚠️ Please choose import method, merge or overwrite?";
97+
"alert.import_hosts_merge" = "merge";
98+
"alert.import_hosts_overwrite" = "⚠️ overwrite";
8099

81100
/* host -- start */
82101
"host.field.region" = "Region";

0 commit comments

Comments
 (0)