Merge pull request #331 from olofhellman/master
Implement 'current article' as scriptable property of the top level object
This commit is contained in:
commit
dc27ca24e6
|
@ -166,6 +166,8 @@
|
||||||
D5A267C120131B8300A8D3C0 /* testFeedOPML.applescript in Sources */ = {isa = PBXBuildFile; fileRef = D5A267B220131B8300A8D3C0 /* testFeedOPML.applescript */; };
|
D5A267C120131B8300A8D3C0 /* testFeedOPML.applescript in Sources */ = {isa = PBXBuildFile; fileRef = D5A267B220131B8300A8D3C0 /* testFeedOPML.applescript */; };
|
||||||
D5A267C220131BA000A8D3C0 /* testFeedOPML.applescript in CopyFiles */ = {isa = PBXBuildFile; fileRef = D5A267B220131B8300A8D3C0 /* testFeedOPML.applescript */; };
|
D5A267C220131BA000A8D3C0 /* testFeedOPML.applescript in CopyFiles */ = {isa = PBXBuildFile; fileRef = D5A267B220131B8300A8D3C0 /* testFeedOPML.applescript */; };
|
||||||
D5D1751220020B980047B29D /* Evergreen.sdef in Resources */ = {isa = PBXBuildFile; fileRef = D5D175012002039D0047B29D /* Evergreen.sdef */; };
|
D5D1751220020B980047B29D /* Evergreen.sdef in Resources */ = {isa = PBXBuildFile; fileRef = D5D175012002039D0047B29D /* Evergreen.sdef */; };
|
||||||
|
D5E4CC54202C1361009B4FFC /* AppDelegate+Scriptability.swift in Sources */ = {isa = PBXBuildFile; fileRef = D5E4CC53202C1361009B4FFC /* AppDelegate+Scriptability.swift */; };
|
||||||
|
D5E4CC64202C1AC1009B4FFC /* MainWindowController+Scriptability.swift in Sources */ = {isa = PBXBuildFile; fileRef = D5E4CC63202C1AC1009B4FFC /* MainWindowController+Scriptability.swift */; };
|
||||||
D5F4EDB5200744A700B9E363 /* ScriptingObject.swift in Sources */ = {isa = PBXBuildFile; fileRef = D5F4EDB4200744A700B9E363 /* ScriptingObject.swift */; };
|
D5F4EDB5200744A700B9E363 /* ScriptingObject.swift in Sources */ = {isa = PBXBuildFile; fileRef = D5F4EDB4200744A700B9E363 /* ScriptingObject.swift */; };
|
||||||
D5F4EDB720074D6500B9E363 /* Feed+Scriptability.swift in Sources */ = {isa = PBXBuildFile; fileRef = D5F4EDB620074D6500B9E363 /* Feed+Scriptability.swift */; };
|
D5F4EDB720074D6500B9E363 /* Feed+Scriptability.swift in Sources */ = {isa = PBXBuildFile; fileRef = D5F4EDB620074D6500B9E363 /* Feed+Scriptability.swift */; };
|
||||||
D5F4EDB920074D7C00B9E363 /* Folder+Scriptability.swift in Sources */ = {isa = PBXBuildFile; fileRef = D5F4EDB820074D7C00B9E363 /* Folder+Scriptability.swift */; };
|
D5F4EDB920074D7C00B9E363 /* Folder+Scriptability.swift in Sources */ = {isa = PBXBuildFile; fileRef = D5F4EDB820074D7C00B9E363 /* Folder+Scriptability.swift */; };
|
||||||
|
@ -654,6 +656,8 @@
|
||||||
D5A2679B201312F900A8D3C0 /* testNameOfAuthors.applescript */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.applescript; path = testNameOfAuthors.applescript; sourceTree = "<group>"; };
|
D5A2679B201312F900A8D3C0 /* testNameOfAuthors.applescript */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.applescript; path = testNameOfAuthors.applescript; sourceTree = "<group>"; };
|
||||||
D5A267B220131B8300A8D3C0 /* testFeedOPML.applescript */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.applescript; path = testFeedOPML.applescript; sourceTree = "<group>"; };
|
D5A267B220131B8300A8D3C0 /* testFeedOPML.applescript */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.applescript; path = testFeedOPML.applescript; sourceTree = "<group>"; };
|
||||||
D5D175012002039D0047B29D /* Evergreen.sdef */ = {isa = PBXFileReference; lastKnownFileType = text.xml; name = Evergreen.sdef; path = ../Resources/Evergreen.sdef; sourceTree = "<group>"; };
|
D5D175012002039D0047B29D /* Evergreen.sdef */ = {isa = PBXFileReference; lastKnownFileType = text.xml; name = Evergreen.sdef; path = ../Resources/Evergreen.sdef; sourceTree = "<group>"; };
|
||||||
|
D5E4CC53202C1361009B4FFC /* AppDelegate+Scriptability.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "AppDelegate+Scriptability.swift"; sourceTree = "<group>"; };
|
||||||
|
D5E4CC63202C1AC1009B4FFC /* MainWindowController+Scriptability.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "MainWindowController+Scriptability.swift"; sourceTree = "<group>"; };
|
||||||
D5F4EDB4200744A700B9E363 /* ScriptingObject.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ScriptingObject.swift; sourceTree = "<group>"; };
|
D5F4EDB4200744A700B9E363 /* ScriptingObject.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ScriptingObject.swift; sourceTree = "<group>"; };
|
||||||
D5F4EDB620074D6500B9E363 /* Feed+Scriptability.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Feed+Scriptability.swift"; sourceTree = "<group>"; };
|
D5F4EDB620074D6500B9E363 /* Feed+Scriptability.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Feed+Scriptability.swift"; sourceTree = "<group>"; };
|
||||||
D5F4EDB820074D7C00B9E363 /* Folder+Scriptability.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Folder+Scriptability.swift"; sourceTree = "<group>"; };
|
D5F4EDB820074D7C00B9E363 /* Folder+Scriptability.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Folder+Scriptability.swift"; sourceTree = "<group>"; };
|
||||||
|
@ -1311,10 +1315,12 @@
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
D5907D962004B7EB005947E5 /* Account+Scriptability.swift */,
|
D5907D962004B7EB005947E5 /* Account+Scriptability.swift */,
|
||||||
|
D5E4CC53202C1361009B4FFC /* AppDelegate+Scriptability.swift */,
|
||||||
D553737C20186C1F006D8857 /* Article+Scriptability.swift */,
|
D553737C20186C1F006D8857 /* Article+Scriptability.swift */,
|
||||||
D5A2678B20130ECF00A8D3C0 /* Author+Scriptability.swift */,
|
D5A2678B20130ECF00A8D3C0 /* Author+Scriptability.swift */,
|
||||||
D5F4EDB620074D6500B9E363 /* Feed+Scriptability.swift */,
|
D5F4EDB620074D6500B9E363 /* Feed+Scriptability.swift */,
|
||||||
D5F4EDB820074D7C00B9E363 /* Folder+Scriptability.swift */,
|
D5F4EDB820074D7C00B9E363 /* Folder+Scriptability.swift */,
|
||||||
|
D5E4CC63202C1AC1009B4FFC /* MainWindowController+Scriptability.swift */,
|
||||||
D5907D7E2004AC00005947E5 /* NSApplication+Scriptability.swift */,
|
D5907D7E2004AC00005947E5 /* NSApplication+Scriptability.swift */,
|
||||||
D5907DB12004BB37005947E5 /* ScriptingObjectContainer.swift */,
|
D5907DB12004BB37005947E5 /* ScriptingObjectContainer.swift */,
|
||||||
D5F4EDB4200744A700B9E363 /* ScriptingObject.swift */,
|
D5F4EDB4200744A700B9E363 /* ScriptingObject.swift */,
|
||||||
|
@ -1891,6 +1897,7 @@
|
||||||
849A97771ED9EC04007D329B /* TimelineCellData.swift in Sources */,
|
849A97771ED9EC04007D329B /* TimelineCellData.swift in Sources */,
|
||||||
84B99C6B1FAE370B00ECDEDB /* FeedListFeed.swift in Sources */,
|
84B99C6B1FAE370B00ECDEDB /* FeedListFeed.swift in Sources */,
|
||||||
841ABA6020145EC100980E11 /* BuiltinSmartFeedInspectorViewController.swift in Sources */,
|
841ABA6020145EC100980E11 /* BuiltinSmartFeedInspectorViewController.swift in Sources */,
|
||||||
|
D5E4CC54202C1361009B4FFC /* AppDelegate+Scriptability.swift in Sources */,
|
||||||
D5F4EDB5200744A700B9E363 /* ScriptingObject.swift in Sources */,
|
D5F4EDB5200744A700B9E363 /* ScriptingObject.swift in Sources */,
|
||||||
D5F4EDB920074D7C00B9E363 /* Folder+Scriptability.swift in Sources */,
|
D5F4EDB920074D7C00B9E363 /* Folder+Scriptability.swift in Sources */,
|
||||||
842611A01FCB72600086A189 /* FeaturedImageDownloader.swift in Sources */,
|
842611A01FCB72600086A189 /* FeaturedImageDownloader.swift in Sources */,
|
||||||
|
@ -1902,6 +1909,7 @@
|
||||||
849A97541ED9EAC0007D329B /* AddFeedWindowController.swift in Sources */,
|
849A97541ED9EAC0007D329B /* AddFeedWindowController.swift in Sources */,
|
||||||
849A976D1ED9EBC8007D329B /* TimelineTableView.swift in Sources */,
|
849A976D1ED9EBC8007D329B /* TimelineTableView.swift in Sources */,
|
||||||
84D52E951FE588BB00D14F5B /* DetailStatusBarView.swift in Sources */,
|
84D52E951FE588BB00D14F5B /* DetailStatusBarView.swift in Sources */,
|
||||||
|
D5E4CC64202C1AC1009B4FFC /* MainWindowController+Scriptability.swift in Sources */,
|
||||||
84B99C671FAE35E600ECDEDB /* FeedListTreeControllerDelegate.swift in Sources */,
|
84B99C671FAE35E600ECDEDB /* FeedListTreeControllerDelegate.swift in Sources */,
|
||||||
84D5BA20201E8FB6009092BD /* SidebarGearMenuDelegate.swift in Sources */,
|
84D5BA20201E8FB6009092BD /* SidebarGearMenuDelegate.swift in Sources */,
|
||||||
84B99C691FAE36B800ECDEDB /* FeedListFolder.swift in Sources */,
|
84B99C691FAE36B800ECDEDB /* FeedListFolder.swift in Sources */,
|
||||||
|
|
|
@ -526,3 +526,26 @@ private extension AppDelegate {
|
||||||
sortByOldestArticleOnTopMenuItem.state = sortByNewestOnTop ? .off : .on
|
sortByOldestArticleOnTopMenuItem.state = sortByNewestOnTop ? .off : .on
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
the ScriptingAppDelegate protocol exposes a narrow set of accessors with
|
||||||
|
internal visibility which are very similar to some private vars.
|
||||||
|
|
||||||
|
These would be unnecessary if the similar accessors were marked internal rather than private,
|
||||||
|
but for now, we'll keep the stratification of visibility
|
||||||
|
*/
|
||||||
|
extension AppDelegate : ScriptingAppDelegate {
|
||||||
|
|
||||||
|
internal var scriptingMainWindowController: ScriptingMainWindowController? {
|
||||||
|
return mainWindowController
|
||||||
|
}
|
||||||
|
|
||||||
|
internal var scriptingCurrentArticle: Article? {
|
||||||
|
return self.scriptingMainWindowController?.scriptingCurrentArticle
|
||||||
|
}
|
||||||
|
|
||||||
|
internal var scriptingSelectedArticles: [Article] {
|
||||||
|
return self.scriptingMainWindowController?.scriptingSelectedArticles ?? []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -400,6 +400,28 @@ extension MainWindowController: NSToolbarDelegate {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// MARK: - Scripting Access
|
||||||
|
|
||||||
|
/*
|
||||||
|
the ScriptingMainWindowController protocol exposes a narrow set of accessors with
|
||||||
|
internal visibility which are very similar to some private vars.
|
||||||
|
|
||||||
|
These would be unnecessary if the similar accessors were marked internal rather than private,
|
||||||
|
but for now, we'll keep the stratification of visibility
|
||||||
|
*/
|
||||||
|
|
||||||
|
extension MainWindowController : ScriptingMainWindowController {
|
||||||
|
|
||||||
|
internal var scriptingCurrentArticle: Article? {
|
||||||
|
return self.oneSelectedArticle
|
||||||
|
}
|
||||||
|
|
||||||
|
internal var scriptingSelectedArticles: [Article] {
|
||||||
|
return self.selectedArticles ?? []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// MARK: - Private
|
// MARK: - Private
|
||||||
|
|
||||||
private extension MainWindowController {
|
private extension MainWindowController {
|
||||||
|
|
|
@ -20,7 +20,13 @@
|
||||||
<!-- the name of the Cocoa class where we have provided the
|
<!-- the name of the Cocoa class where we have provided the
|
||||||
various accessor methods for our application class. -->
|
various accessor methods for our application class. -->
|
||||||
<cocoa class="NSApplication"/>
|
<cocoa class="NSApplication"/>
|
||||||
|
<property name="current article" code="CurA" type="article" access="r" description="The article, if any, being currently displayed">
|
||||||
|
<cocoa key="currentArticle"/>
|
||||||
|
</property>
|
||||||
|
<property name="selected articles" code="SelA" access="r" description="All articles in the main window that are currently selected, if any.">
|
||||||
|
<type type="article" list="yes"/>
|
||||||
|
<cocoa key="selectedArticles"/>
|
||||||
|
</property>
|
||||||
<element type="account">
|
<element type="account">
|
||||||
<cocoa key="accounts"/>
|
<cocoa key="accounts"/>
|
||||||
</element>
|
</element>
|
||||||
|
@ -42,7 +48,7 @@
|
||||||
<property name="name" code="pnam" type="text" access="r" description="The name of the account">
|
<property name="name" code="pnam" type="text" access="r" description="The name of the account">
|
||||||
<cocoa key="name"/>
|
<cocoa key="name"/>
|
||||||
</property>
|
</property>
|
||||||
<property name="id" code="id " type="text" access="r" description="The unique id of the account">
|
<property name="id" code="ID " type="text" access="r" description="The unique id of the account">
|
||||||
<cocoa key="uniqueId"/>
|
<cocoa key="uniqueId"/>
|
||||||
</property>
|
</property>
|
||||||
<property name="type" code="ATyp" type="account type" access="r" description="The type of the account">
|
<property name="type" code="ATyp" type="account type" access="r" description="The type of the account">
|
||||||
|
@ -71,7 +77,7 @@
|
||||||
<property name="name" code="pnam" type="text" access="r" description="The name of the feed">
|
<property name="name" code="pnam" type="text" access="r" description="The name of the feed">
|
||||||
<cocoa key="name"/>
|
<cocoa key="name"/>
|
||||||
</property>
|
</property>
|
||||||
<property name="id" code="id " type="text" access="r" description="The unique id of the account">
|
<property name="id" code="ID " type="text" access="r" description="The unique id of the account">
|
||||||
<cocoa key="uniqueId"/>
|
<cocoa key="uniqueId"/>
|
||||||
</property>
|
</property>
|
||||||
<property name="url" code="URL " type="text" access="r" description="The type of the account">
|
<property name="url" code="URL " type="text" access="r" description="The type of the account">
|
||||||
|
@ -101,7 +107,7 @@
|
||||||
<property name="name" code="pnam" type="text" access="r" description="The name of the author">
|
<property name="name" code="pnam" type="text" access="r" description="The name of the author">
|
||||||
<cocoa key="name"/>
|
<cocoa key="name"/>
|
||||||
</property>
|
</property>
|
||||||
<property name="id" code="id " type="text" access="r" description="The unique id of the author">
|
<property name="id" code="ID " type="text" access="r" description="The unique id of the author">
|
||||||
<cocoa key="uniqueId"/>
|
<cocoa key="uniqueId"/>
|
||||||
</property>
|
</property>
|
||||||
<property name="url" code="URL " type="text" access="r" description="url for the author">
|
<property name="url" code="URL " type="text" access="r" description="url for the author">
|
||||||
|
@ -120,7 +126,7 @@
|
||||||
<property name="name" code="pnam" type="text" access="r" description="The name of the account">
|
<property name="name" code="pnam" type="text" access="r" description="The name of the account">
|
||||||
<cocoa key="name"/>
|
<cocoa key="name"/>
|
||||||
</property>
|
</property>
|
||||||
<property name="id" code="id " type="integer" access="r" description="The unique id of the account">
|
<property name="id" code="ID " type="integer" access="r" description="The unique id of the account">
|
||||||
<cocoa key="uniqueId"/>
|
<cocoa key="uniqueId"/>
|
||||||
</property>
|
</property>
|
||||||
<property name="opml representation" code="OPML" type="text" access="r" description="OPML representation for the folder">
|
<property name="opml representation" code="OPML" type="text" access="r" description="OPML representation for the folder">
|
||||||
|
@ -130,7 +136,7 @@
|
||||||
|
|
||||||
<class name="article" code="Arcl" plural="articles" description="An article in a feed">
|
<class name="article" code="Arcl" plural="articles" description="An article in a feed">
|
||||||
<cocoa class="ScriptableArticle"/>
|
<cocoa class="ScriptableArticle"/>
|
||||||
<property name="id" code="id " type="text" access="r" description="The unique id of the article as set by the feed">
|
<property name="id" code="ID " type="text" access="r" description="The unique id of the article as set by the feed">
|
||||||
<cocoa key="uniqueId"/>
|
<cocoa key="uniqueId"/>
|
||||||
</property>
|
</property>
|
||||||
<property name="title" code="titl" type="text" access="r" description="The article title">
|
<property name="title" code="titl" type="text" access="r" description="The article title">
|
||||||
|
|
|
@ -54,12 +54,29 @@ class ScriptableAccount: NSObject, UniqueIdScriptingObject, ScriptingObjectConta
|
||||||
return feeds.map { ScriptableFeed($0, container:self) } as NSArray
|
return feeds.map { ScriptableFeed($0, container:self) } as NSArray
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@objc(valueInFeedsWithUniqueID:)
|
||||||
|
func valueInFeeds(withUniqueID id:String) -> ScriptableFeed? {
|
||||||
|
let feeds = account.children.compactMap { $0 as? Feed }
|
||||||
|
guard let feed = feeds.first(where:{$0.feedID == id}) else { return nil }
|
||||||
|
return ScriptableFeed(feed, container:self)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@objc(folders)
|
@objc(folders)
|
||||||
var folders:NSArray {
|
var folders:NSArray {
|
||||||
let folders = account.children.compactMap { $0 as? Folder }
|
let folders = account.children.compactMap { $0 as? Folder }
|
||||||
return folders.map { ScriptableFolder($0, container:self) } as NSArray
|
return folders.map { ScriptableFolder($0, container:self) } as NSArray
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@objc(valueInFoldersWithUniqueID:)
|
||||||
|
func valueInFolders(withUniqueID id:NSNumber) -> ScriptableFolder? {
|
||||||
|
let folderId = id.intValue
|
||||||
|
let folders = account.children.compactMap { $0 as? Folder }
|
||||||
|
guard let folder = folders.first(where:{$0.folderID == folderId}) else { return nil }
|
||||||
|
return ScriptableFolder(folder, container:self)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// MARK: --- Scriptable properties ---
|
// MARK: --- Scriptable properties ---
|
||||||
|
|
||||||
@objc(contents)
|
@objc(contents)
|
||||||
|
|
|
@ -0,0 +1,28 @@
|
||||||
|
//
|
||||||
|
// AppDelegate+Scriptability.swift
|
||||||
|
// Evergreen
|
||||||
|
//
|
||||||
|
// Created by Olof Hellman on 2/7/18.
|
||||||
|
// Copyright © 2018 Ranchero Software. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
/*
|
||||||
|
Note: strictly, the AppDelegate doesn't appear as part of the scripting model,
|
||||||
|
so this file is rather unlike the other Object+Scriptability.swift files.
|
||||||
|
However, the AppDelegate object is the de facto scripting accessor for some
|
||||||
|
application elements and properties. For, example, the main window is accessed
|
||||||
|
via the AppDelegate's MainWindowController, and the main window itself has
|
||||||
|
selected feeds, selected articles and a current article. This file supplies the glue to access
|
||||||
|
these scriptable objects, while being completely separate from the core AppDelegate code,
|
||||||
|
*/
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
import Data
|
||||||
|
|
||||||
|
protocol ScriptingAppDelegate {
|
||||||
|
var scriptingCurrentArticle: Article? {get}
|
||||||
|
var scriptingSelectedArticles: [Article] {get}
|
||||||
|
var scriptingMainWindowController:ScriptingMainWindowController? {get}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -85,12 +85,20 @@ class ScriptableFeed: NSObject, UniqueIdScriptingObject, ScriptingObjectContaine
|
||||||
return self.feed.OPMLString(indentLevel:0)
|
return self.feed.OPMLString(indentLevel:0)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// MARK: --- scriptable elements ---
|
||||||
|
|
||||||
@objc(authors)
|
@objc(authors)
|
||||||
var authors:NSArray {
|
var authors:NSArray {
|
||||||
let feedAuthors = feed.authors ?? []
|
let feedAuthors = feed.authors ?? []
|
||||||
return feedAuthors.map { ScriptableAuthor($0, container:self) } as NSArray
|
return feedAuthors.map { ScriptableAuthor($0, container:self) } as NSArray
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@objc(valueInAuthorsWithUniqueID:)
|
||||||
|
func valueInAuthors(withUniqueID id:String) -> ScriptableAuthor? {
|
||||||
|
guard let author = feed.authors?.first(where:{$0.authorID == id}) else { return nil }
|
||||||
|
return ScriptableAuthor(author, container:self)
|
||||||
|
}
|
||||||
|
|
||||||
@objc(articles)
|
@objc(articles)
|
||||||
var articles:NSArray {
|
var articles:NSArray {
|
||||||
let feedArticles = feed.fetchArticles()
|
let feedArticles = feed.fetchArticles()
|
||||||
|
@ -101,4 +109,11 @@ class ScriptableFeed: NSObject, UniqueIdScriptingObject, ScriptingObjectContaine
|
||||||
return sortedArticles.map { ScriptableArticle($0, container:self) } as NSArray
|
return sortedArticles.map { ScriptableArticle($0, container:self) } as NSArray
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@objc(valueInArticlesWithUniqueID:)
|
||||||
|
func valueInArticles(withUniqueID id:String) -> ScriptableArticle? {
|
||||||
|
let articles = feed.fetchArticles()
|
||||||
|
guard let article = articles.first(where:{$0.uniqueID == id}) else { return nil }
|
||||||
|
return ScriptableArticle(article, container:self)
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,16 @@
|
||||||
|
//
|
||||||
|
// MainWindowController+Scriptability.swift
|
||||||
|
// Evergreen
|
||||||
|
//
|
||||||
|
// Created by Olof Hellman on 2/7/18.
|
||||||
|
// Copyright © 2018 Ranchero Software. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
import Data
|
||||||
|
|
||||||
|
protocol ScriptingMainWindowController {
|
||||||
|
var scriptingCurrentArticle: Article? { get }
|
||||||
|
var scriptingSelectedArticles: [Article] { get }
|
||||||
|
}
|
||||||
|
|
|
@ -20,27 +20,74 @@ extension NSApplication : ScriptingObjectContainer {
|
||||||
return "application"
|
return "application"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@objc(currentArticle)
|
||||||
|
func currentArticle() -> ScriptableArticle? {
|
||||||
|
var scriptableArticle: ScriptableArticle?
|
||||||
|
if let currentArticle = appDelegate.scriptingCurrentArticle {
|
||||||
|
if let feed = currentArticle.feed {
|
||||||
|
let scriptableFeed = ScriptableFeed(feed, container:self)
|
||||||
|
scriptableArticle = ScriptableArticle(currentArticle, container:scriptableFeed)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return scriptableArticle
|
||||||
|
}
|
||||||
|
|
||||||
|
@objc(selectedArticles)
|
||||||
|
func selectedArticles() -> NSArray {
|
||||||
|
let articles = appDelegate.scriptingSelectedArticles
|
||||||
|
let scriptableArticles:[ScriptableArticle] = articles.compactMap { article in
|
||||||
|
if let feed = article.feed {
|
||||||
|
let scriptableFeed = ScriptableFeed(feed, container:self)
|
||||||
|
return ScriptableArticle(article, container:scriptableFeed)
|
||||||
|
} else {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return scriptableArticles as NSArray
|
||||||
|
}
|
||||||
|
|
||||||
|
// MARK: --- scriptable elements ---
|
||||||
|
|
||||||
@objc(accounts)
|
@objc(accounts)
|
||||||
func accounts() -> NSArray {
|
func accounts() -> NSArray {
|
||||||
let accounts = AccountManager.shared.accounts
|
let accounts = AccountManager.shared.accounts
|
||||||
return accounts.map { ScriptableAccount($0) } as NSArray
|
return accounts.map { ScriptableAccount($0) } as NSArray
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@objc(valueInAccountsWithUniqueID:)
|
||||||
|
func valueInAccounts(withUniqueID id:String) -> ScriptableAccount? {
|
||||||
|
let accounts = AccountManager.shared.accounts
|
||||||
|
guard let account = accounts.first(where:{$0.accountID == id}) else { return nil }
|
||||||
|
return ScriptableAccount(account)
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
accessing feeds from the application object skips the 'account' containment hierarchy
|
accessing feeds from the application object skips the 'account' containment hierarchy
|
||||||
this allows a script like 'articles of feed "The Shape of Everything"' as a shorthand
|
this allows a script like 'articles of feed "The Shape of Everything"' as a shorthand
|
||||||
for 'articles of feed "The Shape of Everything" of account "On My Mac"'
|
for 'articles of feed "The Shape of Everything" of account "On My Mac"'
|
||||||
*/
|
*/
|
||||||
@objc(feeds)
|
|
||||||
func feeds() -> NSArray {
|
func allFeeds() -> [Feed] {
|
||||||
let accounts = AccountManager.shared.accounts
|
let accounts = AccountManager.shared.accounts
|
||||||
let emptyFeeds:[Feed] = []
|
let emptyFeeds:[Feed] = []
|
||||||
let feeds = accounts.reduce(emptyFeeds) { (result, nthAccount) -> [Feed] in
|
return accounts.reduce(emptyFeeds) { (result, nthAccount) -> [Feed] in
|
||||||
let accountFeeds = nthAccount.children.compactMap { $0 as? Feed }
|
let accountFeeds = nthAccount.children.compactMap { $0 as? Feed }
|
||||||
return result + accountFeeds
|
return result + accountFeeds
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@objc(feeds)
|
||||||
|
func feeds() -> NSArray {
|
||||||
|
let feeds = self.allFeeds()
|
||||||
return feeds.map { ScriptableFeed($0, container:self) } as NSArray
|
return feeds.map { ScriptableFeed($0, container:self) } as NSArray
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@objc(valueInFeedsWithUniqueID:)
|
||||||
|
func valueInFeeds(withUniqueID id:String) -> ScriptableFeed? {
|
||||||
|
let feeds = self.allFeeds()
|
||||||
|
guard let feed = feeds.first(where:{$0.feedID == id}) else { return nil }
|
||||||
|
return ScriptableFeed(feed, container:self)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue