diff --git a/NEWS.md b/NEWS.md index fcc3831..f41f6a4 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,3 +1,10 @@ +# 1.3.0 + +- revamped app icon +- revamped menubar icon (shld work better on light/dark switching) +- handles existing filenames in a cleaner fashion +- more informative download alerts + # 1.2.0 - numbered key equivalents (up to 9) diff --git a/README.md b/README.md index 83cdfbf..f88b717 100644 --- a/README.md +++ b/README.md @@ -3,13 +3,15 @@ ![Minimum macOS Target](https://img.shields.io/badge/macOS-10.14%2B-blue) ![License](https://img.shields.io/badge/License-MIT-blue.svg) +![](rswitch.png) + # RSwitch Change 'Current' R version on macOS ## Description -At the bottom of the [R for macOS Developer's Page](http://mac.r-project.org/) there's mention of an "other binary" called "RSwitch" that is _"a small GUI that allows you to switch between R versions quickly (if you have multiple versions of R framework installed)."_ Said switching requires you to use the "tar.gz" versions of R from the R for macOS Developer's Page since the official CRAN binary installers clean up after themselves quite nicely to prevent potentially wacky behavior. +At the bottom of the [R for macOS Developer's Page](https://mac.r-project.org/) there's mention of an "other binary" called "RSwitch" that is _"a small GUI that allows you to switch between R versions quickly (if you have multiple versions of R framework installed)."_ Said switching requires you to use the "tar.gz" versions of R from the R for macOS Developer's Page since the official CRAN binary installers clean up after themselves quite nicely to prevent potentially wacky behavior. All this GUI does is change the `Current` alias target in `/Library/Frameworks/R.framework/Versions` to the appropriate version. You can do that from the command line but the switcher GUI was created so that means some folks prefer click-switching. @@ -58,10 +60,10 @@ This codebase has been uploaded to the following authoritative social coding sit ## TODO -- Clean up the icon (which is "dial" by IconMark from the Noun Project). This means having it look better in the menu bar in dark/light mode _including_ the highlight mode for it. Possibly means getting a visible "R" on it somewhere. -- Better/prettier alerting (which also means more sanity checks) - Allow hiding of the app icon? (not sure this is a good idea, tho…pls discuss in an issue!) - (add your own TODO suggestions via PR) +- Clean up the icon (which is "dial" by IconMark from the Noun Project). This means having it look better in the menu bar in dark/light mode _including_ the highlight mode for it. Possibly means getting a visible "R" on it somewhere. +- Better/prettier alerting (which also means more sanity checks) - Add Cmd-1, -2, -3, (etc) key equivalents in the menu bar for fast selection (one reason why ^^ might not be a good idea) - Add an "about" box (mostly to ensure IconMark gets more credit than a comment and README) diff --git a/RSwitch.xcodeproj/project.pbxproj b/RSwitch.xcodeproj/project.pbxproj index fa78b59..7f18550 100644 --- a/RSwitch.xcodeproj/project.pbxproj +++ b/RSwitch.xcodeproj/project.pbxproj @@ -3,7 +3,7 @@ archiveVersion = 1; classes = { }; - objectVersion = 50; + objectVersion = 51; objects = { /* Begin PBXBuildFile section */ @@ -85,7 +85,6 @@ 53FF56D90FA7100C1726A4F7 /* Pods-RSwitch.debug.xcconfig */, 574911021B3B7938E36AB013 /* Pods-RSwitch.release.xcconfig */, ); - name = Pods; path = Pods; sourceTree = ""; }; @@ -355,7 +354,7 @@ "@executable_path/../Frameworks", ); MACOSX_DEPLOYMENT_TARGET = 10.14; - MARKETING_VERSION = 1.2.0; + MARKETING_VERSION = 1.3.0; PRODUCT_BUNDLE_IDENTIFIER = is.rud.bob.RSwitch; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = ""; @@ -379,7 +378,7 @@ "@executable_path/../Frameworks", ); MACOSX_DEPLOYMENT_TARGET = 10.14; - MARKETING_VERSION = 1.2.0; + MARKETING_VERSION = 1.3.0; PRODUCT_BUNDLE_IDENTIFIER = is.rud.bob.RSwitch; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = ""; diff --git a/RSwitch/AppDelegate.swift b/RSwitch/AppDelegate.swift index e6a4d31..5f2f7f0 100644 --- a/RSwitch/AppDelegate.swift +++ b/RSwitch/AppDelegate.swift @@ -3,25 +3,17 @@ import SwiftSoup // Show an informational alert public func infoAlert(_ message: String, _ extra: String? = nil, style: NSAlert.Style = NSAlert.Style.informational) { - let alert = NSAlert() - alert.messageText = message - if extra != nil { alert.informativeText = extra! } - alert.alertStyle = style - alert.runModal() } // Show an informational alert and then quit public func quitAlert(_ message: String, _ extra: String? = nil) { - infoAlert(message, "The application will now quit.", style: NSAlert.Style.critical) - NSApp.terminate(nil) - } @NSApplicationMain @@ -30,9 +22,11 @@ class AppDelegate: NSObject, NSApplicationDelegate { var mainStoryboard: NSStoryboard! var abtController: NSWindowController! - - // Where the official R installs go - let macos_r_framework_dir = "/Library/Frameworks/R.framework/Versions" + let macos_r_framework_dir = "/Library/Frameworks/R.framework/Versions" // Where the official R installs go + let mac_r_project_url = "https://mac.r-project.org/" + let macos_cran_url = "https://cran.rstudio.org/bin/macosx/" + let r_sig_mac_url = "https://stat.ethz.ch/pipermail/r-sig-mac/" + let rstudio_dailies_url = "https://dailies.rstudio.com/rstudio/oss/mac/" // Get the bar setup let statusItem = NSStatusBar.system.statusItem(withLength: NSStatusItem.variableLength) @@ -87,25 +81,25 @@ class AppDelegate: NSObject, NSApplicationDelegate { // browse macOS dev page @objc func browse_r_macos_dev_page(_ sender: NSMenuItem?) { - let url = URL(string: "https://mac.r-project.org/")! + let url = URL(string: mac_r_project_url)! NSWorkspace.shared.open(url) } // browse macOS dev page @objc func browse_r_macos_cran_page(_ sender: NSMenuItem?) { - let url = URL(string: "https://cran.rstudio.org/bin/macosx/")! + let url = URL(string: macos_cran_url)! NSWorkspace.shared.open(url) } // browse macOS dev page @objc func browse_r_sig_mac_page(_ sender: NSMenuItem?) { - let url = URL(string: "https://stat.ethz.ch/pipermail/r-sig-mac/")! + let url = URL(string: r_sig_mac_url)! NSWorkspace.shared.open(url) } // browse RStudio macOS Dailies @objc func browse_rstudio_mac_dailies_page(_ sender: NSMenuItem?) { - let url = URL(string: "https://dailies.rstudio.com/rstudio/oss/mac/")! + let url = URL(string: rstudio_dailies_url)! NSWorkspace.shared.open(url) } @@ -122,7 +116,7 @@ class AppDelegate: NSObject, NSApplicationDelegate { // Download latest rstudio daily build @objc func download_latest_rstudio(_ sender: NSMenuItem?) { - let url = URL(string: "https://dailies.rstudio.com/rstudio/oss/mac/") + let url = URL(string: rstudio_dailies_url) do { let html = try String.init(contentsOf: url!) @@ -133,33 +127,31 @@ class AppDelegate: NSObject, NSApplicationDelegate { let dlurl = URL(string: href)! let dldir = FileManager.default.urls(for: .downloadsDirectory, in: .userDomainMask).first! var dlfile = dldir + dlfile.appendPathComponent(dlurl.lastPathComponent) - let task = URLSession.shared.downloadTask(with: dlurl) { (tempURL, response, error) in - if let tempURL = tempURL, error == nil { - if ((response as? HTTPURLResponse)?.statusCode == 200) { - - do { - - try FileManager.default.copyItem(at: tempURL, to: dlfile) - NSWorkspace.shared.openFile(dldir.path, withApplication: "Finder") - - DispatchQueue.main.async { infoAlert("Download of latest RStudio daily successful.") } - - } catch { - DispatchQueue.main.async { infoAlert("Error downloading and saving latest RStudio daily.") } + if (FileManager.default.fileExists(atPath: dlfile.relativePath)) { + infoAlert("A local copy of the latest RStudio daily already exists. Please remove or rename it if you wish to re-download it.") + } else { + let task = URLSession.shared.downloadTask(with: dlurl) { (tempURL, response, error) in + if let tempURL = tempURL, error == nil { + if ((response as? HTTPURLResponse)?.statusCode == 200) { + do { + try FileManager.default.copyItem(at: tempURL, to: dlfile) + NSWorkspace.shared.openFile(dldir.path, withApplication: "Finder") + DispatchQueue.main.async { infoAlert("Download of latest RStudio daily (" + dlurl.lastPathComponent + ") successful.") } + } catch { + DispatchQueue.main.async { infoAlert("Error downloading and saving latest RStudio daily.") } + } + } else { + DispatchQueue.main.async { infoAlert("Latest RStudio daily not found.") } } - } else { - DispatchQueue.main.async { infoAlert("Latest RStudio daily not found.") } + DispatchQueue.main.async { infoAlert("Error downloading latest RStudio daily.") } } - } else { - DispatchQueue.main.async { infoAlert("Error downloading latest RStudio daily.") } } + task.resume() } - - task.resume() - } catch { DispatchQueue.main.async { infoAlert("Error downloading latrest RStudio daily.") } } @@ -172,33 +164,32 @@ class AppDelegate: NSObject, NSApplicationDelegate { let url = URL(string: "https://mac.r-project.org/el-capitan/R-devel/R-devel-el-capitan-sa-x86_64.tar.gz")! let dldir = FileManager.default.urls(for: .downloadsDirectory, in: .userDomainMask).first! var dlfile = dldir + dlfile.appendPathComponent("R-devel-el-capitan-sa-x86_64.tar.gz") - let task = URLSession.shared.downloadTask(with: url) { (tempURL, response, error) in - if let tempURL = tempURL, error == nil { - if ((response as? HTTPURLResponse)?.statusCode == 200) { - - do { - - try FileManager.default.copyItem(at: tempURL, to: dlfile) - NSWorkspace.shared.openFile(dldir.path, withApplication: "Finder") - - DispatchQueue.main.async { infoAlert("Download of latest r-devel successful.") } - - - } catch { - DispatchQueue.main.async { infoAlert("Error downloading and saving latest r-devel .") } + + if (FileManager.default.fileExists(atPath: dlfile.relativePath)) { + infoAlert("R-devel tarball already exists. Please remove or rename it before downloading.") + } else { + let task = URLSession.shared.downloadTask(with: url) { (tempURL, response, error) in + if let tempURL = tempURL, error == nil { + if ((response as? HTTPURLResponse)?.statusCode == 200) { + do { + try FileManager.default.copyItem(at: tempURL, to: dlfile) + NSWorkspace.shared.openFile(dldir.path, withApplication: "Finder") + DispatchQueue.main.async { infoAlert("Download of latest r-devel successful.") } + } catch { + DispatchQueue.main.async { infoAlert("Error downloading and saving latest r-devel .") } + } + } else { + DispatchQueue.main.async { infoAlert("Latest r-devel file not found.") } + } + } else { + DispatchQueue.main.async { infoAlert("Error downloading latest r-devel .") } } - - } else { - DispatchQueue.main.async { infoAlert("Latest r-devel file not found.") } } - } else { - DispatchQueue.main.async { infoAlert("Error downloading latest r-devel .") } - } + task.resume() } - - task.resume() } } diff --git a/RSwitch/Base.lproj/Main.storyboard b/RSwitch/Base.lproj/Main.storyboard index e494233..e00bfa9 100644 --- a/RSwitch/Base.lproj/Main.storyboard +++ b/RSwitch/Base.lproj/Main.storyboard @@ -741,7 +741,7 @@ -RSwitch v1.2.0 +RSwitch v1.3.0 Copyright © 2019 Bob Rudis diff --git a/releases/RSwitch-1.3.0.app.zip b/releases/RSwitch-1.3.0.app.zip new file mode 100644 index 0000000..5702d75 Binary files /dev/null and b/releases/RSwitch-1.3.0.app.zip differ diff --git a/rswitch.png b/rswitch.png new file mode 100644 index 0000000..37d4947 Binary files /dev/null and b/rswitch.png differ