package de.unixwork.rssreader
import de.unixwork.ui.Application
-import de.unixwork.ui.Container.grid
-import de.unixwork.ui.Text.textfield
import de.unixwork.ui.ToolbarPosition
import de.unixwork.ui.Toolkit
import de.unixwork.ui.kotlin.ToolkitDispatcher
import de.unixwork.ui.kotlin.toolbarToggleItem
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.GlobalScope
-import kotlinx.coroutines.IO
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
-import org.h2.api.H2Type.row
import java.io.IOException
import java.time.LocalDate
markCurrentFeedAsRead()
}
- toolbarToggleItem(name = "starred", icon = "starred", varname = "starred", tooltip = "star the current item") { event ->
+ toolbarToggleItem(name = "starred", icon = "starred", varname = "starred", tooltip = "Star the current item") { event ->
setBookmark(event.intValue == 1)
}
+ toolbarToggleItem(name = "preview", icon = "view-reveal", varname = "browser", tooltip = "Open the current item uri in the internal webview") { event ->
+ window?.feedList?.updateWebView()
+ }
toolbarAppMenu {
menuItem(label = "Update All") {
addToolbarDefault("reloadFeed", ToolbarPosition.LEFT)
addToolbarDefault("markCurrentFeed", ToolbarPosition.LEFT)
addToolbarDefault("starred", ToolbarPosition.RIGHTPANEL_LEFT)
+ addToolbarDefault("preview", position = ToolbarPosition.RIGHTPANEL_LEFT)
}
override fun startup() {
feedcollection_id INT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
group_id INT NOT NULL REFERENCES groups(group_id) ON DELETE CASCADE,
pos INT default 0,
+ internal_browser INT default 0,
name VARCHAR,
update_interval INT,
max_item_age INT DEFAULT 0,
f.name as feed_name,
f.update_interval,
f.item_state_mode,
+ f.internal_browser,
c.unread_count
from groups g
left join feedcollections f on g.group_id = f.group_id
val feedId = rs.getInt("feedcollection_id")
val feedName = rs.getString("feed_name")
val updateInterval = rs.getLong("update_interval")
+ val internalBrowser = rs.getBoolean("internal_browser")
val itemStateMode = rs.getInt("item_state_mode")
val unreadCount = rs.getInt("unread_count")
val feed = FeedCollection(feedId, feedName)
feed.updateInterval = updateInterval
feed.itemStateMode = itemStateMode
+ feed.internalBrowser = internalBrowser
feed.unreadItemsCount = unreadCount
currentGroup.feeds.add(feed)
}
user: String? = null,
password: String? = null,
cert: String? = null,
+ internalBrowser: Boolean = false,
updateInterval: Long = 0,
maxItemAge: Int = 0,
itemStateMode: Int = 0) : FeedCollection
var updateInterval: Long = 0
var itemStateMode = 0
var unreadItemsCount = 0
+ var internalBrowser = false
var items = mutableListOf<Item>()
var itemsLoaded = false
import de.unixwork.ui.kotlin.ToolkitDispatcher
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.GlobalScope
-import kotlinx.coroutines.IO
import kotlinx.coroutines.launch
-import java.awt.Desktop
-import java.net.URI
-import java.net.URISyntaxException
class FeedList(window: MainWindow) : Document() {
val window = window
val webview = webview("webview")
val tabview = integer("tabview")
val starred = integer("starred")
- val preview = integer("preview")
+ val browser = integer("browser")
// Feed that is currently shown
var currentFeed: FeedCollection? = null
} else {
starred.setIntValue(0)
}
- val content = item.getContent()
- webview.loadContent(item.link, content.text, content.type, "utf-8")
- tabview.setIntValue(1)
- preview.setIntValue(0) // reset preview toggle button
+ tabview.setIntValue(1) // select item page
+
+ currentFeed?.let { feed ->
+ browser.setBooleanValue(feed.internalBrowser)
+ } ?: {
+ browser.setBooleanValue(false)
+ }
+
+ updateWebView()
// Update read status
if(!item.isRead) {
}
}
- fun togglePreview() {
+ fun updateWebView() {
currentItem?.let { item ->
- if(preview.intValue() == 0) {
+ if(browser.booleanValue()) {
+ webview.loadUrl(item.link)
+ // TODO: enable when more browser features (go prev/next) are implemented
+ //window.window.ui.setState(MainWindow.ITEM_INTERNAL_BROWSER)
+ } else {
val content = item.getContent()
webview.loadContent(item.link, content.text, content.type, "utf-8")
- } else {
- webview.loadUrl(item.link)
+ window.window.ui.unsetState(MainWindow.ITEM_INTERNAL_BROWSER)
}
}
}
import de.unixwork.ui.UiString
import de.unixwork.ui.UiText
import de.unixwork.ui.kotlin.Toplevel
-import de.unixwork.ui.kotlin.sidebarWindow
import de.unixwork.ui.kotlin.dialogWindow
import de.unixwork.ui.kotlin.openFileDialog
import de.unixwork.ui.kotlin.setDefaultWindowSize
companion object {
const val ITEM_HAS_AUTHOR = 1000
const val ITEM_HAS_CATEGORY = 1001
+ const val ITEM_INTERNAL_BROWSER = 1002
}
val window : Toplevel
var currentSublistIndex = -1
var currentFeedIndex = -1
+ var browserSetting = 0 // 0: use browser setting from feed, 1: always use internal browser, 2: never use internal browser
+
init {
setDefaultWindowSize(1600, 900)
window = splitViewWindow(title = "RSS Reader", sidebar = true) {
varname = "items",
fill = true,
onSelection = { event ->
- if(event.set != 0) {
+ if(event.set) {
// Don't handle set events: in some toolkit implementations, updating the
- // list triggers a onSelection event
+ // list triggers an onSelection event
return@table
}
feedList.items.selected?.let {
rlabel("Link:", hfill = true)
linkbutton(varname = "link", styleClass = "ui-nopadding");
}
+
row {
- hbox(spacing = 4, colspan = 2) {
- linkbutton(label = "Browser", varname = "link2", type = LinkButtonType.BUTTON)
- togglebutton (label = "Preview", tooltip = "Open article in the internal webview", varname = "preview") { event ->
- if(event.set == 0) {
- feedList.togglePreview()
- }
+ vbox(hfill = true, vfill = true, hexpand = true, vexpand = true, colspan = 2) {
+ hbox(spacing = 4, visibilityStates = intArrayOf(ITEM_INTERNAL_BROWSER)) {
+ button(icon = "go-previous")
+ button(icon = "go-next")
+ textfield(varname = "web-uri", fill = true)
}
+ webview(varname = "webview", fill = true, colspan = 2)
}
}
-
- row {
- webview(varname = "webview", hfill = true, vfill = true, hexpand = true, vexpand = true, colspan = 2)
- }
}
}
}
parent?.let {
try {
val feedCol = Database.newFeeds(
- it,
- feedName,
- uris,
- user.toString(),
- password.toString(),
- cert.toString(),
- 0, // TODO
- maxItemAge,
- itemStateMode
+ parent = it,
+ name = feedName,
+ uris = uris,
+ user = user.toString(),
+ password = password.toString(),
+ cert = cert.toString(),
+ internalBrowser = false,
+ updateInterval = 0, // TODO
+ maxItemAge = maxItemAge,
+ itemStateMode = itemStateMode
)
parent.feeds.update()
private int columnspacing;
private int rowspacing;
+ private int[] visibilityStates;
+
public ContainerBuilder(UiObject obj, MethodHandle widgetConstructor) {
this.obj = obj;
this.widgetConstructor = widgetConstructor;
return this;
}
+ public ContainerBuilder visibilityStates(int[] states) {
+ this.visibilityStates = states;
+ return this;
+ }
+
@Override
public MemorySegment createArgs(Arena arena) throws Throwable {
ArgFuncs ui = ArgFuncs.getInstance();
Container container = createContainer();
ui.callback();
container.close();
- return container.getWidget();
+ UiWidget w = container.getWidget();
+ if(visibilityStates != null) {
+ w.setVisibilityStates(visibilityStates);
+ }
+ return w;
}
}
private Object windowData;
private Object eventData;
private int intval;
- private int set;
+ private boolean set;
private MemorySegment windowPtr;
private MemorySegment documentPtr;
document = toolkit.getDocument(documentPtr.address());
intval = (int)ui.event_get_int.invoke(eventPtr);
- set = (int)ui.event_get_set.invoke(eventPtr);
+ set = ((int)ui.event_get_set.invoke(eventPtr)) != 0;
eventDataPtr = (MemorySegment)ui.event_get_eventdata.invoke(eventPtr);
int type = (int)ui.event_get_eventdatatype.invoke(eventPtr);
this.intval = intval;
}
- public int getSet() { return set; }
+ public boolean getSet() { return set; }
- public void setSet(int set) { this.set = set; }
+ public void setSet(boolean set) { this.set = set; }
public MemorySegment getWindowPtr() {
return windowPtr;
public void setIntValue(int value) {
setLongValue(value);
}
+
+ public boolean booleanValue() {
+ return longValue() != 0;
+ }
+
+ public void setBooleanValue(boolean value) {
+ setLongValue(value ? 1 : 0);
+ }
}
spacing: Int = -1,
columnspacing: Int = -1,
rowspacing: Int = -1,
+ visibilityStates: IntArray? = null,
ui: ContainerUI? = null
): UiWidget {
if(fill) {
if(rowspacing > 0) {
container.rowspacing(rowspacing)
}
+ if(visibilityStates != null) {
+ container.visibilityStates(visibilityStates)
+ }
return container.create(ui)
}
name: String? = null,
styleClass: String? = null,
spacing: Int = -1,
+ visibilityStates: IntArray? = null,
ui: ContainerUI? = null
): UiWidget {
return createContainer(
name = name,
styleClass = styleClass,
spacing = spacing,
+ visibilityStates = visibilityStates,
ui = ui
)
}
name: String? = null,
styleClass: String? = null,
spacing: Int = -1,
+ visibilityStates: IntArray? = null,
ui: ContainerUI? = null
): UiWidget {
return createContainer(
name = name,
styleClass = styleClass,
spacing = spacing,
+ visibilityStates = visibilityStates,
ui = ui
)
}
spacing: Int = -1,
columnspacing: Int = -1,
rowspacing: Int = -1,
+ visibilityStates: IntArray? = null,
ui: ContainerUI? = null
): UiWidget {
return createContainer(
spacing = spacing,
columnspacing = columnspacing,
rowspacing = rowspacing,
+ visibilityStates = visibilityStates,
ui = ui
)
}