Skip to content

Commit

Permalink
[Feature] Add tab, and preferences
Browse files Browse the repository at this point in the history
- Change Backup Session to Latest Session
- Add preferences view for showing latest session
- Change add new url -> add current tab
  • Loading branch information
phucledien committed Jun 12, 2020
1 parent edb2d3e commit 5007f24
Show file tree
Hide file tree
Showing 12 changed files with 418 additions and 102 deletions.
69 changes: 46 additions & 23 deletions SessionBuddy Extension/SafariExtensionHandler.swift
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,52 @@ import SafariServices

class SafariExtensionHandler: SFSafariExtensionHandler {

override func messageReceived(withName messageName: String, from page: SFSafariPage, userInfo: [String : Any]?) {
// This method will be called when a content script provided by your extension calls safari.extension.dispatchMessage("message").
page.getPropertiesWithCompletionHandler { properties in
NSLog("The extension received a message (\(messageName)) from a script injected into (\(String(describing: properties?.url))) with userInfo (\(userInfo ?? [:]))")
override func messageReceived(
withName messageName: String,
from page: SFSafariPage,
userInfo: [String : Any]?) {

// This method will be called when a content script provided by
// your extension calls safari.extension.dispatchMessage("message").
if messageName == "DOMContentLoaded" || messageName == "BeforeUnload" {
DispatchQueue.global(qos: .userInitiated).async {
self.saveLatestSession()
}
}
}

private func saveLatestSession() {
guard Preferences.showLatestSession else {return}

// Get old backupSessionIdx
LocalStorage.sessions.removeAll(where: \.isBackup)

SFSafariApplication.getActiveWindow { window in
window?.getAllTabs { tabs in
var sessionTabs = [Tab]()

for (index, tab) in tabs.enumerated() {
tab.getActivePage { page in
page?.getPropertiesWithCompletionHandler { properties in
if let url = properties?.url?.absoluteString,
let title = properties?.title {
sessionTabs.append(Tab(title: title, url: url))
}

// Last element
if index == tabs.count - 1 {
var newSession = Session(
title: "Latest Session",
tabs: sessionTabs)

newSession.isBackup = true
LocalStorage.sessions = [newSession] + LocalStorage.sessions
NotificationCenter.default.post(Notification(name: Notification.Name("sessionDidChange")))
}
}
}
}
}
}
}

Expand All @@ -30,23 +72,4 @@ class SafariExtensionHandler: SFSafariExtensionHandler {
override func popoverViewController() -> SFSafariExtensionViewController {
return SafariExtensionViewController.shared
}

override func page(_ page: SFSafariPage, willNavigateTo url: URL?) {
guard let url = url else {return}

// Handle auto backup session
if let backupSessionIdx = LocalStorage.sessions.firstIndex(where: { $0.isBackup }) {
// Update existed backup session
var backupSessionTabs = LocalStorage.sessions[backupSessionIdx].tabs
backupSessionTabs.append(Tab(title: url.absoluteString, url: url.absoluteString))
// just add unique URL
LocalStorage.sessions[backupSessionIdx].tabs = backupSessionTabs.unique()
} else {
// Create new backup session
var backupSession = Session(title: "Backups - \(Date().commonStringFormat())", tabs: [Tab(title: url.absoluteString, url: url.absoluteString)])
backupSession.isBackup = true
LocalStorage.sessions.append(backupSession)
}

}
}
76 changes: 46 additions & 30 deletions SessionBuddy Extension/Views/DetailView/DetailViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ class DetailViewController: NSViewController {

private var isMultiFuncViewShowing = false

private var newTabURL: String?

init(session: Session) {
self.session = session
super.init(nibName: "DetailViewController", bundle: Bundle.main)
Expand Down Expand Up @@ -82,7 +84,7 @@ class DetailViewController: NSViewController {
btnAction.isEnabled = true
containerViewActionInput.isHidden = false
containerViewActions.isHidden = true

txtfieldAction.placeholderString = "Session name"
txtfieldAction.stringValue = session.title
txtfieldAction.becomeFirstResponder()
}
Expand All @@ -92,6 +94,7 @@ class DetailViewController: NSViewController {
btnAction.isEnabled = false
containerViewActionInput.isHidden = false
containerViewActions.isHidden = true
txtfieldAction.placeholderString = "[email protected]"
txtfieldAction.becomeFirstResponder()
}

Expand Down Expand Up @@ -123,28 +126,30 @@ class DetailViewController: NSViewController {
}

private func share(with email: String) {
do {
let jsonEncoder = JSONEncoder()
jsonEncoder.outputFormatting = .prettyPrinted
let data = try jsonEncoder.encode(ImportExportData(data: [session]))

let tempDir = try FileManager.default.url(for: .cachesDirectory, in: .userDomainMask, appropriateFor: nil, create: false)
let fileURL = tempDir.appendingPathComponent("\(Date().saveFileStringFormat()).json")

try data.write(to: fileURL)

let sharingService = NSSharingService(named: .composeEmail)
sharingService?.delegate = self

sharingService?.recipients = [email]
sharingService?.subject = "Sharing my Session Buddy session"
let items: [Any] = ["see attachment", fileURL]
sharingService?.perform(withItems: items)

} catch {
NSLog(error.localizedDescription)
Util.showErrorDialog(text: "Data is corrupted, please contact us for more support")
}
guard let session =
LocalStorage.sessions.first(where: { $0.id == self.session.id })
else {return}

let jsonEncoder = JSONEncoder()
jsonEncoder.outputFormatting = .prettyPrinted

guard
let subjectEncoded = "[Session Buddy] Share my session".addingPercentEncoding(withAllowedCharacters: .urlHostAllowed),
let bodyEncodedData = try? jsonEncoder.encode(session),
var body = String(data: bodyEncodedData, encoding: .utf8)
else {return}

body = """
Please copy the content below and save it as file.json to import in Session Buddy
\(body)
"""
guard
let bodyEncoded = body.addingPercentEncoding(withAllowedCharacters: .alphanumerics),
let defaultUrl = URL(string: "mailto:\(email)?subject=\(subjectEncoded)&body=\(bodyEncoded)")
else {return}

NSWorkspace.shared.open(defaultUrl)
}

@IBAction func deleteSession(_ sender: Any) {
Expand All @@ -167,9 +172,15 @@ class DetailViewController: NSViewController {
tab?.getActivePage(completionHandler: { page in
page?.getPropertiesWithCompletionHandler { properties in
DispatchQueue.main.async {
self.txtfieldURL.stringValue = properties?.url?.absoluteString ?? ""
guard
let title = properties?.title,
let url = properties?.url
else {return}

self.txtfieldURL.stringValue = title
self.txtfieldURL.becomeFirstResponder()
self.btnAdd.isEnabled = !self.txtfieldURL.stringValue.isEmpty
self.newTabURL = url.absoluteString
}
}
})
Expand All @@ -187,9 +198,12 @@ class DetailViewController: NSViewController {
self.containerEditview.isHidden = true
self.btnAddUrl.isHidden = false

guard !txtfieldURL.stringValue.isEmpty else {return}
guard
!txtfieldURL.stringValue.isEmpty,
let url = self.newTabURL
else {return}

let newTab = Tab(title: txtfieldURL.stringValue, url: txtfieldURL.stringValue)
let newTab = Tab(title: txtfieldURL.stringValue, url: url)
self.tabs.append(newTab)
self.updateSession(with: self.tabs)

Expand All @@ -215,7 +229,7 @@ extension DetailViewController: NSTableViewDelegate {

cell.set(
title: tabs[row].title,
onDelete: self.onDelete(at: row)
onDelete: self.onDelete(id: tabs[row].id)
)

return cell
Expand All @@ -231,13 +245,15 @@ extension DetailViewController: NSTableViewDelegate {
return false
}

private func onDelete(at index: Int) -> (() -> Void) {
private func onDelete(id: String) -> (() -> Void) {
return {
self.tabs.remove(at: index)
guard let idx = self.tabs.firstIndex(where: { $0.id == id }) else {return}

self.tabs.remove(at: idx)
self.updateSession(with: self.tabs)

DispatchQueue.main.async {
self.tableView.removeRows(at: .init(integer: index), withAnimation: .effectFade)
self.tableView.removeRows(at: .init(integer: idx), withAnimation: .effectFade)
}

self.shouldReload = true
Expand Down
15 changes: 7 additions & 8 deletions SessionBuddy Extension/Views/DetailView/DetailViewController.xib
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@
</textFieldCell>
</textField>
<button verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="g6K-Gs-2IT">
<rect key="frame" x="289.5" y="231" width="47" height="23"/>
<rect key="frame" x="288.5" y="231" width="48" height="23"/>
<buttonCell key="cell" type="roundTextured" title="Open" bezelStyle="texturedRounded" alignment="center" borderStyle="border" imageScaling="proportionallyUpOrDown" inset="2" id="YrO-fW-Ucx">
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
<font key="font" metaFont="system"/>
Expand All @@ -148,8 +148,8 @@
<rect key="frame" x="0.0" y="0.0" width="344" height="50"/>
<subviews>
<button verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="PsF-pz-itA">
<rect key="frame" x="12" y="15" width="80" height="21"/>
<buttonCell key="cell" type="square" bezelStyle="shadowlessSquare" image="btn_add_url" imagePosition="only" alignment="center" imageScaling="proportionallyUpOrDown" inset="2" id="aTF-kV-soS">
<rect key="frame" x="11.5" y="13" width="110" height="23"/>
<buttonCell key="cell" type="roundTextured" title="Add current tab" bezelStyle="texturedRounded" alignment="center" borderStyle="border" imageScaling="proportionallyUpOrDown" inset="2" id="aTF-kV-soS">
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
<font key="font" metaFont="system"/>
</buttonCell>
Expand All @@ -162,7 +162,7 @@
<subviews>
<textField verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="d91-cE-Siu">
<rect key="frame" x="0.0" y="0.0" width="241" height="26"/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" selectable="YES" editable="YES" sendsActionOnEndEditing="YES" borderStyle="bezel" drawsBackground="YES" id="jPK-4c-Udx">
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" selectable="YES" editable="YES" sendsActionOnEndEditing="YES" borderStyle="bezel" placeholderString="Tab title" drawsBackground="YES" id="jPK-4c-Udx">
<font key="font" usesAppearanceFont="YES"/>
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
Expand Down Expand Up @@ -225,7 +225,7 @@ DQ
<rect key="frame" x="8" y="199" width="328" height="20"/>
<subviews>
<stackView distribution="fillEqually" orientation="horizontal" alignment="centerY" horizontalStackHuggingPriority="249.99998474121094" verticalStackHuggingPriority="249.99998474121094" detachesHiddenViews="YES" translatesAutoresizingMaskIntoConstraints="NO" id="BnX-HY-53G">
<rect key="frame" x="100" y="0.0" width="128" height="20"/>
<rect key="frame" x="71" y="0.0" width="187" height="20"/>
<subviews>
<button verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="qch-bE-GK3">
<rect key="frame" x="0.0" y="0.0" width="67" height="20"/>
Expand Down Expand Up @@ -253,8 +253,8 @@ DQ
<action selector="deleteSession:" target="-2" id="CPy-O4-kUM"/>
</connections>
</button>
<button hidden="YES" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="vxU-kA-507">
<rect key="frame" x="0.0" y="-10" width="51" height="30"/>
<button verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="vxU-kA-507">
<rect key="frame" x="136" y="0.0" width="51" height="20"/>
<constraints>
<constraint firstAttribute="width" constant="51" id="YIu-wO-sam"/>
</constraints>
Expand Down Expand Up @@ -389,7 +389,6 @@ DQ
<image name="NSTouchBarComposeTemplate" width="21" height="30"/>
<image name="NSTouchBarDeleteTemplate" width="15" height="30"/>
<image name="NSTouchBarShareTemplate" width="15" height="30"/>
<image name="btn_add_url" width="80" height="21"/>
<image name="ico_circle" width="13" height="13"/>
</resources>
</document>
4 changes: 2 additions & 2 deletions SessionBuddy Extension/Views/Import/ImportViewController.xib
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
</textFieldCell>
</textField>
<button verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="FKw-gs-67h">
<rect key="frame" x="282.5" y="59" width="54" height="23"/>
<rect key="frame" x="282" y="59" width="54" height="23"/>
<buttonCell key="cell" type="roundTextured" title="Import" bezelStyle="texturedRounded" alignment="center" borderStyle="border" imageScaling="proportionallyUpOrDown" inset="2" id="WDg-MZ-apL">
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
<font key="font" metaFont="system"/>
Expand All @@ -38,7 +38,7 @@
</connections>
</button>
<button verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="wEH-5q-yeN">
<rect key="frame" x="7.5" y="59" width="28" height="23"/>
<rect key="frame" x="8" y="59" width="27" height="23"/>
<constraints>
<constraint firstAttribute="width" constant="27" id="1sc-B4-IZl"/>
</constraints>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
//
// PreferencesViewConttroller.swift
// Session Buddy Extension
//
// Created by phucld on 6/11/20.
// Copyright © 2020 Dwarves Foundation. All rights reserved.
//

import Cocoa

class PreferencesViewConttroller: NSViewController {

@IBOutlet weak var checkboxShowLatestSession: NSButton!

var onNavigationBack: ((Bool) -> Void)?

private var shouldUpdate = false

override func viewDidLoad() {
super.viewDidLoad()
setupViews()
}

func set(onNavigationBack: @escaping ((Bool) -> Void)) {
self.onNavigationBack = onNavigationBack
}

private func setupViews() {
checkboxShowLatestSession.state = Preferences.showLatestSession ? .on : .off
}

@IBAction func toggleShowTheLatestSession(_ sender: Any) {
Preferences.showLatestSession = checkboxShowLatestSession.state == .on
if checkboxShowLatestSession.state == .on {
LocalStorage.sessions.removeAll(where: (\.isBackup))
NotificationCenter.default.post(Notification(name: Notification.Name("sessionDidChange")))
}

shouldUpdate = true
}

@IBAction func backToPrevious(_ sender: Any) {
self.onNavigationBack?(shouldUpdate)
self.view.removeFromSuperview()
self.removeFromParent()
}

}
Loading

0 comments on commit 5007f24

Please sign in to comment.