Split into a seperate daemon
This commit is contained in:
parent
21ceb10d7e
commit
30b4d01543
10
Makefile
10
Makefile
|
@ -30,20 +30,17 @@ APP_MIME_SIG = application/x-vnd.Pogger
|
||||||
# Also note that spaces in folder names do not work well with this Makefile.
|
# Also note that spaces in folder names do not work well with this Makefile.
|
||||||
SRCS = \
|
SRCS = \
|
||||||
src/App.cpp \
|
src/App.cpp \
|
||||||
src/AtomFeed.cpp \
|
|
||||||
src/DeskbarView.cpp \
|
|
||||||
src/Entry.cpp \
|
src/Entry.cpp \
|
||||||
src/EntriesView.cpp \
|
src/EntriesView.cpp \
|
||||||
src/Feed.cpp \
|
src/Feed.cpp \
|
||||||
src/FeedController.cpp \
|
|
||||||
src/FeedEditWindow.cpp \
|
src/FeedEditWindow.cpp \
|
||||||
src/FeedListItem.cpp \
|
src/FeedListItem.cpp \
|
||||||
|
src/FeedSource.cpp \
|
||||||
src/FeedsView.cpp \
|
src/FeedsView.cpp \
|
||||||
|
src/LocalSource.cpp \
|
||||||
src/MainWindow.cpp \
|
src/MainWindow.cpp \
|
||||||
src/Mimetypes.cpp \
|
src/Mimetypes.cpp \
|
||||||
src/Notifier.cpp \
|
|
||||||
src/Preferences.cpp \
|
src/Preferences.cpp \
|
||||||
src/RssFeed.cpp \
|
|
||||||
src/UpdatesView.cpp \
|
src/UpdatesView.cpp \
|
||||||
src/Util.cpp
|
src/Util.cpp
|
||||||
|
|
||||||
|
@ -155,3 +152,6 @@ DRIVER_PATH =
|
||||||
## Include the Makefile-Engine
|
## Include the Makefile-Engine
|
||||||
DEVEL_DIRECTORY := /boot/system/develop/
|
DEVEL_DIRECTORY := /boot/system/develop/
|
||||||
include $(DEVEL_DIRECTORY)/etc/makefile-engine
|
include $(DEVEL_DIRECTORY)/etc/makefile-engine
|
||||||
|
|
||||||
|
# Differentiate between Pogger and PoggerShadow's catkeys
|
||||||
|
CATKEYS_DIR = locales/app
|
||||||
|
|
|
@ -0,0 +1,155 @@
|
||||||
|
## Haiku Generic Makefile v2.6 ##
|
||||||
|
|
||||||
|
## Fill in this file to specify the project being created, and the referenced
|
||||||
|
## Makefile-Engine will do all of the hard work for you. This handles any
|
||||||
|
## architecture of Haiku.
|
||||||
|
|
||||||
|
# The name of the binary.
|
||||||
|
NAME = PoggerShadow
|
||||||
|
|
||||||
|
# The type of binary, must be one of:
|
||||||
|
# APP: Application
|
||||||
|
# SHARED: Shared library or add-on
|
||||||
|
# STATIC: Static library archive
|
||||||
|
# DRIVER: Kernel driver
|
||||||
|
TYPE = APP
|
||||||
|
|
||||||
|
# If you plan to use localization, specify the application's MIME signature.
|
||||||
|
APP_MIME_SIG = application/x-vnd.PoggerDaemon
|
||||||
|
|
||||||
|
# The following lines tell Pe and Eddie where the SRCS, RDEFS, and RSRCS are
|
||||||
|
# so that Pe and Eddie can fill them in for you.
|
||||||
|
#%{
|
||||||
|
# @src->@
|
||||||
|
|
||||||
|
# Specify the source files to use. Full paths or paths relative to the
|
||||||
|
# Makefile can be included. All files, regardless of directory, will have
|
||||||
|
# their object files created in the common object directory. Note that this
|
||||||
|
# means this Makefile will not work correctly if two source files with the
|
||||||
|
# same name (source.c or source.cpp) are included from different directories.
|
||||||
|
# Also note that spaces in folder names do not work well with this Makefile.
|
||||||
|
SRCS = \
|
||||||
|
src/AtomFeed.cpp \
|
||||||
|
src/Daemon.cpp \
|
||||||
|
src/DeskbarView.cpp \
|
||||||
|
src/Entry.cpp \
|
||||||
|
src/Feed.cpp \
|
||||||
|
src/FeedController.cpp \
|
||||||
|
src/FeedSource.cpp \
|
||||||
|
src/LocalSource.cpp \
|
||||||
|
src/Notifier.cpp \
|
||||||
|
src/Preferences.cpp \
|
||||||
|
src/RssFeed.cpp \
|
||||||
|
src/Util.cpp
|
||||||
|
|
||||||
|
# Specify the resource definition files to use. Full or relative paths can be
|
||||||
|
# used.
|
||||||
|
RDEFS = \
|
||||||
|
src/Daemon.rdef \
|
||||||
|
img/icons/FeedIcon.rdef \
|
||||||
|
img/icons/EntryIcon.rdef \
|
||||||
|
img/icons/PoggerIcon.rdef
|
||||||
|
|
||||||
|
|
||||||
|
# Specify the resource files to use. Full or relative paths can be used.
|
||||||
|
# Both RDEFS and RSRCS can be utilized in the same Makefile.
|
||||||
|
RSRCS = \
|
||||||
|
|
||||||
|
|
||||||
|
# End Pe/Eddie support.
|
||||||
|
# @<-src@
|
||||||
|
#%}
|
||||||
|
|
||||||
|
#%}
|
||||||
|
|
||||||
|
#%}
|
||||||
|
|
||||||
|
# Specify libraries to link against.
|
||||||
|
# There are two acceptable forms of library specifications:
|
||||||
|
# - if your library follows the naming pattern of libXXX.so or libXXX.a,
|
||||||
|
# you can simply specify XXX for the library. (e.g. the entry for
|
||||||
|
# "libtracker.so" would be "tracker")
|
||||||
|
#
|
||||||
|
# - for GCC-independent linking of standard C++ libraries, you can use
|
||||||
|
# $(STDCPPLIBS) instead of the raw "stdc++[.r4] [supc++]" library names.
|
||||||
|
#
|
||||||
|
# - if your library does not follow the standard library naming scheme,
|
||||||
|
# you need to specify the path to the library and it's name.
|
||||||
|
# (e.g. for mylib.a, specify "mylib.a" or "path/mylib.a")
|
||||||
|
LIBS = be bnetapi localestub network netservices shared tinyxml2 tracker $(STDCPPLIBS)
|
||||||
|
|
||||||
|
# Specify additional paths to directories following the standard libXXX.so
|
||||||
|
# or libXXX.a naming scheme. You can specify full paths or paths relative
|
||||||
|
# to the Makefile. The paths included are not parsed recursively, so
|
||||||
|
# include all of the paths where libraries must be found. Directories where
|
||||||
|
# source files were specified are automatically included.
|
||||||
|
LIBPATHS =
|
||||||
|
|
||||||
|
# Additional paths to look for system headers. These use the form
|
||||||
|
# "#include <header>". Directories that contain the files in SRCS are
|
||||||
|
# NOT auto-included here.
|
||||||
|
SYSTEM_INCLUDE_PATHS = \
|
||||||
|
$(shell findpaths -e B_FIND_PATH_HEADERS_DIRECTORY private/netservices) \
|
||||||
|
# $(shell findpaths -e B_FIND_PATH_HEADERS_DIRECTORY private/interface) \
|
||||||
|
# $(shell findpaths -e B_FIND_PATH_HEADERS_DIRECTORY private/support)
|
||||||
|
|
||||||
|
# Additional paths paths to look for local headers. These use the form
|
||||||
|
# #include "header". Directories that contain the files in SRCS are
|
||||||
|
# automatically included.
|
||||||
|
LOCAL_INCLUDE_PATHS =
|
||||||
|
|
||||||
|
# Specify the level of optimization that you want. Specify either NONE (O0),
|
||||||
|
# SOME (O1), FULL (O2), or leave blank (for the default optimization level).
|
||||||
|
OPTIMIZE := FULL
|
||||||
|
|
||||||
|
# Specify the codes for languages you are going to support in this
|
||||||
|
# application. The default "en" one must be provided too. "make catkeys"
|
||||||
|
# will recreate only the "locales/en.catkeys" file. Use it as a template
|
||||||
|
# for creating catkeys for other languages. All localization files must be
|
||||||
|
# placed in the "locales" subdirectory.
|
||||||
|
LOCALES = en eo
|
||||||
|
|
||||||
|
# Specify all the preprocessor symbols to be defined. The symbols will not
|
||||||
|
# have their values set automatically; you must supply the value (if any) to
|
||||||
|
# use. For example, setting DEFINES to "DEBUG=1" will cause the compiler
|
||||||
|
# option "-DDEBUG=1" to be used. Setting DEFINES to "DEBUG" would pass
|
||||||
|
# "-DDEBUG" on the compiler's command line.
|
||||||
|
DEFINES =
|
||||||
|
|
||||||
|
# Specify the warning level. Either NONE (suppress all warnings),
|
||||||
|
# ALL (enable all warnings), or leave blank (enable default warnings).
|
||||||
|
WARNINGS =
|
||||||
|
|
||||||
|
# With image symbols, stack crawls in the debugger are meaningful.
|
||||||
|
# If set to "TRUE", symbols will be created.
|
||||||
|
SYMBOLS :=
|
||||||
|
|
||||||
|
# Includes debug information, which allows the binary to be debugged easily.
|
||||||
|
# If set to "TRUE", debug info will be created.
|
||||||
|
DEBUGGER :=
|
||||||
|
|
||||||
|
# Specify any additional compiler flags to be used.
|
||||||
|
COMPILER_FLAGS =
|
||||||
|
|
||||||
|
# Specify any additional linker flags to be used.
|
||||||
|
LINKER_FLAGS =
|
||||||
|
|
||||||
|
# Specify the version of this binary. Example:
|
||||||
|
# -app 3 4 0 d 0 -short 340 -long "340 "`echo -n -e '\302\251'`"1999 GNU GPL"
|
||||||
|
# This may also be specified in a resource.
|
||||||
|
APP_VERSION :=
|
||||||
|
|
||||||
|
# (Only used when "TYPE" is "DRIVER"). Specify the desired driver install
|
||||||
|
# location in the /dev hierarchy. Example:
|
||||||
|
# DRIVER_PATH = video/usb
|
||||||
|
# will instruct the "driverinstall" rule to place a symlink to your driver's
|
||||||
|
# binary in ~/add-ons/kernel/drivers/dev/video/usb, so that your driver will
|
||||||
|
# appear at /dev/video/usb when loaded. The default is "misc".
|
||||||
|
DRIVER_PATH =
|
||||||
|
|
||||||
|
## Include the Makefile-Engine
|
||||||
|
DEVEL_DIRECTORY := /boot/system/develop/
|
||||||
|
include $(DEVEL_DIRECTORY)/etc/makefile-engine
|
||||||
|
|
||||||
|
# We need to differentiate between Pogger and PoggerShadow's catkeys
|
||||||
|
CATKEYS_DIR = locales/daemon
|
|
@ -28,8 +28,9 @@ In "Updates" you can toggle notifications and set the frequency of updates.
|
||||||
|
|
||||||
## Building
|
## Building
|
||||||
|
|
||||||
`$ make`
|
`$ make; make -f Makefile-Daemon`
|
||||||
`$ make bindcatalogs`
|
|
||||||
|
`$ make bindcatalogs; make -f Makefile-Daemon bindcatalogs`
|
||||||
|
|
||||||
Uses netservices, and has TinyXML2 as a dependency.
|
Uses netservices, and has TinyXML2 as a dependency.
|
||||||
|
|
||||||
|
|
99
src/App.cpp
99
src/App.cpp
|
@ -5,13 +5,12 @@
|
||||||
|
|
||||||
#include "App.h"
|
#include "App.h"
|
||||||
|
|
||||||
#include <MessageRunner.h>
|
#include <Messenger.h>
|
||||||
#include <Roster.h>
|
#include <Roster.h>
|
||||||
#include <StorageKit.h>
|
#include <StorageKit.h>
|
||||||
#include <String.h>
|
#include <String.h>
|
||||||
|
|
||||||
#include "AtomFeed.h"
|
#include "AtomFeed.h"
|
||||||
#include "DeskbarView.h"
|
|
||||||
#include "Entry.h"
|
#include "Entry.h"
|
||||||
#include "Feed.h"
|
#include "Feed.h"
|
||||||
#include "FeedController.h"
|
#include "FeedController.h"
|
||||||
|
@ -33,20 +32,9 @@ App::App() : BApplication("application/x-vnd.Pogger")
|
||||||
fMainWindow = new MainWindow();
|
fMainWindow = new MainWindow();
|
||||||
fMainWindow->Show();
|
fMainWindow->Show();
|
||||||
|
|
||||||
fNotifier = new Notifier();
|
BRoster roster;
|
||||||
fFeedController = new FeedController();
|
if (roster.IsRunning("application/x-vnd.PoggerDaemon") == false)
|
||||||
|
roster.Launch("application/x-vnd.PoggerDaemon");
|
||||||
BMessage updateMessage(kUpdateSubscribed);
|
|
||||||
int64 interval = fPreferences->UpdateInterval();
|
|
||||||
int32 count = -1;
|
|
||||||
|
|
||||||
if (interval == -1)
|
|
||||||
count = 0;
|
|
||||||
else
|
|
||||||
MessageReceived(&updateMessage);
|
|
||||||
|
|
||||||
fUpdateRunner = new BMessageRunner(this, updateMessage, interval, count);
|
|
||||||
installDeskbar();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -56,39 +44,22 @@ App::MessageReceived(BMessage* msg)
|
||||||
switch (msg->what)
|
switch (msg->what)
|
||||||
{
|
{
|
||||||
case kDownloadComplete:
|
case kDownloadComplete:
|
||||||
fMainWindow->PostMessage(msg);
|
|
||||||
case kEnqueueFeed:
|
|
||||||
case kUpdateSubscribed:
|
|
||||||
case kControllerCheck:
|
|
||||||
{
|
|
||||||
fFeedController->MessageReceived(msg);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case kFeedsEdited:
|
case kFeedsEdited:
|
||||||
case kDownloadStart:
|
case kDownloadStart:
|
||||||
{
|
|
||||||
fMainWindow->PostMessage(msg);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case kClearQueue:
|
|
||||||
{
|
|
||||||
fFeedController->MessageReceived(msg);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case kProgress:
|
case kProgress:
|
||||||
case kParseComplete:
|
case kParseComplete:
|
||||||
case kParseFail:
|
case kParseFail:
|
||||||
case kDownloadFail:
|
case kDownloadFail:
|
||||||
{
|
{
|
||||||
fNotifier->MessageReceived(msg);
|
|
||||||
fMainWindow->PostMessage(msg);
|
fMainWindow->PostMessage(msg);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case B_SILENT_RELAUNCH:
|
case kClearQueue:
|
||||||
|
case kEnqueueFeed:
|
||||||
|
case kUpdateSubscribed:
|
||||||
{
|
{
|
||||||
if (fMainWindow->IsMinimized() == true)
|
BMessenger toDaemon("application/x-vnd.PoggerDaemon");
|
||||||
fMainWindow->Minimize(false);
|
toDaemon.SendMessage(msg);
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
{
|
{
|
||||||
|
@ -102,13 +73,11 @@ App::MessageReceived(BMessage* msg)
|
||||||
bool
|
bool
|
||||||
App::QuitRequested()
|
App::QuitRequested()
|
||||||
{
|
{
|
||||||
delete fUpdateRunner, fFeedController, fNotifier;
|
|
||||||
if (fMainWindow->Lock())
|
if (fMainWindow->Lock())
|
||||||
fMainWindow->Quit();
|
fMainWindow->Quit();
|
||||||
|
|
||||||
fPreferences->Save();
|
fPreferences->Save();
|
||||||
delete fPreferences;
|
delete fPreferences;
|
||||||
removeDeskbar();
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -167,54 +136,8 @@ App::RefsReceived(BMessage* message)
|
||||||
void
|
void
|
||||||
App::_OpenEntryFile(BMessage* refMessage)
|
App::_OpenEntryFile(BMessage* refMessage)
|
||||||
{
|
{
|
||||||
entry_ref entryRef;
|
BRoster roster;
|
||||||
refMessage->FindRef("refs", &entryRef);
|
roster.Launch("application/x-vnd.Pogger", refMessage);
|
||||||
BFile entryFile(&entryRef, B_WRITE_ONLY);
|
|
||||||
|
|
||||||
BString readStatus("Read");
|
|
||||||
entryFile.WriteAttrString("Feed:status", &readStatus);
|
|
||||||
|
|
||||||
if (fPreferences->EntryOpenAsHtml())
|
|
||||||
_OpenEntryFileAsHtml(entryRef);
|
|
||||||
else
|
|
||||||
_OpenEntryFileAsUrl(entryRef);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
App::_OpenEntryFileAsHtml(entry_ref ref)
|
|
||||||
{
|
|
||||||
const char* openWith = fPreferences->EntryOpenWith();
|
|
||||||
entry_ref openWithRef;
|
|
||||||
BString entryTitle("untitled");
|
|
||||||
BFile(&ref, B_READ_ONLY).ReadAttrString("Feed:name", &entryTitle);
|
|
||||||
|
|
||||||
entry_ref tempRef = tempHtmlFile(&ref, entryTitle.String());
|
|
||||||
BMessage newRefMessage(B_REFS_RECEIVED);
|
|
||||||
newRefMessage.AddRef("refs", &tempRef);
|
|
||||||
|
|
||||||
if (BMimeType(openWith).IsValid())
|
|
||||||
BRoster().Launch(openWith, &newRefMessage);
|
|
||||||
else if (BEntry(openWith).GetRef(&openWithRef) == B_OK)
|
|
||||||
BRoster().Launch(&openWithRef, &newRefMessage);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
App::_OpenEntryFileAsUrl(entry_ref ref)
|
|
||||||
{
|
|
||||||
const char* openWith = fPreferences->EntryOpenWith();
|
|
||||||
entry_ref openWithRef;
|
|
||||||
BString entryUrl;
|
|
||||||
if (BFile(&ref, B_READ_ONLY).ReadAttrString("META:url", &entryUrl) != B_OK)
|
|
||||||
return;
|
|
||||||
|
|
||||||
const char* urlArg = entryUrl.String();
|
|
||||||
|
|
||||||
if (BMimeType(openWith).IsValid())
|
|
||||||
BRoster().Launch(openWith, 1, &urlArg);
|
|
||||||
else if (BEntry(openWith).GetRef(&openWithRef) == B_OK)
|
|
||||||
BRoster().Launch(&openWithRef, 1, &urlArg);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -30,16 +30,10 @@ public:
|
||||||
|
|
||||||
MainWindow* fMainWindow;
|
MainWindow* fMainWindow;
|
||||||
Preferences* fPreferences;
|
Preferences* fPreferences;
|
||||||
Notifier* fNotifier;
|
|
||||||
BMessageRunner* fUpdateRunner;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void _OpenEntryFile(BMessage* refMessage);
|
void _OpenEntryFile(BMessage* refMessage);
|
||||||
void _OpenEntryFileAsHtml(entry_ref ref);
|
|
||||||
void _OpenEntryFileAsUrl(entry_ref ref);
|
|
||||||
void _OpenSourceFile(BMessage* refMessage);
|
void _OpenSourceFile(BMessage* refMessage);
|
||||||
|
|
||||||
FeedController* fFeedController;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,225 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2021, Jaidyn Levesque <jadedctrl@teknik.io>
|
||||||
|
* All rights reserved. Distributed under the terms of the MIT license.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "Daemon.h"
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
#include <MessageRunner.h>
|
||||||
|
#include <Roster.h>
|
||||||
|
#include <Url.h>
|
||||||
|
|
||||||
|
#include "DeskbarView.h"
|
||||||
|
#include "FeedController.h"
|
||||||
|
#include "Notifier.h"
|
||||||
|
#include "Preferences.h"
|
||||||
|
#include "Util.h"
|
||||||
|
|
||||||
|
|
||||||
|
App::App() : BApplication("application/x-vnd.PoggerDaemon")
|
||||||
|
{
|
||||||
|
fPreferences = new Preferences;
|
||||||
|
fPreferences->Load();
|
||||||
|
|
||||||
|
fFeedController = new FeedController();
|
||||||
|
fNotifier = new Notifier();
|
||||||
|
|
||||||
|
BMessage updateMessage(kUpdateSubscribed);
|
||||||
|
int64 interval = fPreferences->UpdateInterval();
|
||||||
|
int32 count = -1;
|
||||||
|
|
||||||
|
if (interval == -1)
|
||||||
|
count = 0;
|
||||||
|
else
|
||||||
|
MessageReceived(&updateMessage);
|
||||||
|
fUpdateRunner = new BMessageRunner(this, updateMessage, interval, count);
|
||||||
|
|
||||||
|
installDeskbar();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
App::MessageReceived(BMessage* msg)
|
||||||
|
{
|
||||||
|
switch(msg->what)
|
||||||
|
{
|
||||||
|
case kPreferencesUpdated:
|
||||||
|
{
|
||||||
|
_ReloadPreferences();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case kEnqueueFeed:
|
||||||
|
case kUpdateSubscribed:
|
||||||
|
case kControllerCheck:
|
||||||
|
case kClearQueue:
|
||||||
|
{
|
||||||
|
fFeedController->MessageReceived(msg);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case kProgress:
|
||||||
|
case kParseComplete:
|
||||||
|
case kParseFail:
|
||||||
|
case kDownloadFail:
|
||||||
|
fNotifier->MessageReceived(msg);
|
||||||
|
case kDownloadComplete:
|
||||||
|
case kDownloadStart:
|
||||||
|
{
|
||||||
|
BMessenger toApp("application/x-vnd.Pogger");
|
||||||
|
if (toApp.IsValid())
|
||||||
|
toApp.SendMessage(msg);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
BApplication::MessageReceived(msg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool
|
||||||
|
App::QuitRequested()
|
||||||
|
{
|
||||||
|
delete fUpdateRunner, fFeedController, fPreferences;
|
||||||
|
removeDeskbar();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
App::ArgvReceived(int32 argc, char** argv)
|
||||||
|
{
|
||||||
|
BMessage refMsg(B_REFS_RECEIVED);
|
||||||
|
|
||||||
|
for (int i = 1; i < argc; i++) {
|
||||||
|
entry_ref ref;
|
||||||
|
BEntry entry(argv[i]);
|
||||||
|
|
||||||
|
if (entry.Exists() && entry.GetRef(&ref) == B_OK) {
|
||||||
|
refMsg.AddRef("refs", &ref);
|
||||||
|
}
|
||||||
|
else if (BUrl(argv[i]).IsValid()) {
|
||||||
|
BString url = BString(argv[i]);
|
||||||
|
|
||||||
|
BMessage enqueue = BMessage(kEnqueueFeed);
|
||||||
|
enqueue.AddData("feedPaths", B_STRING_TYPE, &url, sizeof(BString));
|
||||||
|
MessageReceived(&enqueue);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
RefsReceived(&refMsg);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
App::RefsReceived(BMessage* message)
|
||||||
|
{
|
||||||
|
int i = 0;
|
||||||
|
entry_ref ref;
|
||||||
|
BFile file;
|
||||||
|
BNodeInfo info;
|
||||||
|
char type[B_FILE_NAME_LENGTH];
|
||||||
|
|
||||||
|
while (message->HasRef("refs", i)) {
|
||||||
|
BMessage msg(B_REFS_RECEIVED);
|
||||||
|
message->FindRef("refs", i++, &ref);
|
||||||
|
msg.AddRef("refs", &ref);
|
||||||
|
|
||||||
|
file.SetTo(&ref, B_READ_ONLY);
|
||||||
|
info.SetTo(&file);
|
||||||
|
info.GetType(type);
|
||||||
|
|
||||||
|
if (BString(type) == "application/x-feed-entry"
|
||||||
|
|| BString(type) == "text/x-feed-entry")
|
||||||
|
_OpenEntryFile(&msg);
|
||||||
|
else if (BString(type) == "application/x-feed-source")
|
||||||
|
_OpenSourceFile(&msg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
App::_OpenEntryFile(BMessage* refMessage)
|
||||||
|
{
|
||||||
|
entry_ref entryRef;
|
||||||
|
refMessage->FindRef("refs", &entryRef);
|
||||||
|
BFile entryFile(&entryRef, B_WRITE_ONLY);
|
||||||
|
|
||||||
|
BString readStatus("Read");
|
||||||
|
entryFile.WriteAttrString("Feed:status", &readStatus);
|
||||||
|
|
||||||
|
if (fPreferences->EntryOpenAsHtml())
|
||||||
|
_OpenEntryFileAsHtml(entryRef);
|
||||||
|
else
|
||||||
|
_OpenEntryFileAsUrl(entryRef);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
App::_OpenEntryFileAsHtml(entry_ref ref)
|
||||||
|
{
|
||||||
|
const char* openWith = fPreferences->EntryOpenWith();
|
||||||
|
entry_ref openWithRef;
|
||||||
|
BString entryTitle("untitled");
|
||||||
|
BFile(&ref, B_READ_ONLY).ReadAttrString("Feed:name", &entryTitle);
|
||||||
|
|
||||||
|
entry_ref tempRef = tempHtmlFile(&ref, entryTitle.String());
|
||||||
|
BMessage newRefMessage(B_REFS_RECEIVED);
|
||||||
|
newRefMessage.AddRef("refs", &tempRef);
|
||||||
|
|
||||||
|
if (BMimeType(openWith).IsValid())
|
||||||
|
BRoster().Launch(openWith, &newRefMessage);
|
||||||
|
else if (BEntry(openWith).GetRef(&openWithRef) == B_OK)
|
||||||
|
BRoster().Launch(&openWithRef, &newRefMessage);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
App::_OpenEntryFileAsUrl(entry_ref ref)
|
||||||
|
{
|
||||||
|
const char* openWith = fPreferences->EntryOpenWith();
|
||||||
|
entry_ref openWithRef;
|
||||||
|
BString entryUrl;
|
||||||
|
if (BFile(&ref, B_READ_ONLY).ReadAttrString("META:url", &entryUrl) != B_OK)
|
||||||
|
return;
|
||||||
|
|
||||||
|
const char* urlArg = entryUrl.String();
|
||||||
|
|
||||||
|
if (BMimeType(openWith).IsValid())
|
||||||
|
BRoster().Launch(openWith, 1, &urlArg);
|
||||||
|
else if (BEntry(openWith).GetRef(&openWithRef) == B_OK)
|
||||||
|
BRoster().Launch(&openWithRef, 1, &urlArg);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
App::_OpenSourceFile(BMessage* refMessage)
|
||||||
|
{
|
||||||
|
BRoster roster;
|
||||||
|
roster.Launch("application/x-vnd.Pogger", refMessage);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
App::_ReloadPreferences()
|
||||||
|
{
|
||||||
|
fPreferences->Load();
|
||||||
|
int64 interval = fPreferences->UpdateInterval();
|
||||||
|
|
||||||
|
if (interval == -1)
|
||||||
|
fUpdateRunner->SetCount(0);
|
||||||
|
else {
|
||||||
|
fUpdateRunner->SetCount(-1);
|
||||||
|
fUpdateRunner->SetInterval(interval);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int
|
||||||
|
main(int argc, char** arv)
|
||||||
|
{
|
||||||
|
App app;
|
||||||
|
app.Run();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,41 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2021, Jaidyn Levesque <jadedctrl@teknik.io>
|
||||||
|
* All rights reserved. Distributed under the terms of the MIT license.
|
||||||
|
*/
|
||||||
|
#ifndef SHADOWPOG_H
|
||||||
|
#define SHADOWPOG_H
|
||||||
|
|
||||||
|
#include <Application.h>
|
||||||
|
|
||||||
|
class FeedController;
|
||||||
|
class Notifier;
|
||||||
|
class Preferences;
|
||||||
|
|
||||||
|
|
||||||
|
class App : public BApplication {
|
||||||
|
public:
|
||||||
|
App();
|
||||||
|
|
||||||
|
void MessageReceived(BMessage* msg);
|
||||||
|
bool QuitRequested();
|
||||||
|
|
||||||
|
void ArgvReceived(int32 argc, char** argv);
|
||||||
|
void RefsReceived(BMessage* message);
|
||||||
|
|
||||||
|
Preferences* fPreferences;
|
||||||
|
BMessageRunner* fUpdateRunner;
|
||||||
|
|
||||||
|
private:
|
||||||
|
void _OpenEntryFile(BMessage* refMessage);
|
||||||
|
void _OpenEntryFileAsHtml(entry_ref ref);
|
||||||
|
void _OpenEntryFileAsUrl(entry_ref ref);
|
||||||
|
void _OpenSourceFile(BMessage* refMessage);
|
||||||
|
|
||||||
|
void _ReloadPreferences();
|
||||||
|
|
||||||
|
FeedController* fFeedController;
|
||||||
|
Notifier* fNotifier;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif // SHADOWPOG_H
|
|
@ -0,0 +1,22 @@
|
||||||
|
/*
|
||||||
|
* Copyight 2021 Jaidyn Levesque <jadedctrl@teknik.io>
|
||||||
|
* All rights reserved. Distributed under the terms of the MIT License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
resource app_signature "application/x-vnd.PoggerDaemon";
|
||||||
|
|
||||||
|
resource app_flags B_SINGLE_LAUNCH | B_BACKGROUND_APP;
|
||||||
|
|
||||||
|
resource app_version {
|
||||||
|
major = 0,
|
||||||
|
middle = 0,
|
||||||
|
minor = 1,
|
||||||
|
|
||||||
|
short_info = "Pogger daemon",
|
||||||
|
long_info = "Background daemon for Pogger"
|
||||||
|
};
|
||||||
|
|
||||||
|
resource file_types message {
|
||||||
|
"types" = "application/x-feed-entry",
|
||||||
|
"types" = "application/x-feed-source"
|
||||||
|
};
|
|
@ -50,7 +50,7 @@ status_t
|
||||||
DeskbarView::Archive(BMessage* data, bool deep) const {
|
DeskbarView::Archive(BMessage* data, bool deep) const {
|
||||||
BView::Archive(data, deep);
|
BView::Archive(data, deep);
|
||||||
|
|
||||||
data->AddString("add_on", "application/x-vnd.Pogger");
|
data->AddString("add_on", "application/x-vnd.PoggerDaemon");
|
||||||
data->AddString("class", "Pogger");
|
data->AddString("class", "Pogger");
|
||||||
|
|
||||||
return B_OK;
|
return B_OK;
|
||||||
|
@ -97,7 +97,7 @@ DeskbarView::MessageReceived(BMessage* msg)
|
||||||
}
|
}
|
||||||
case kUpdateNow:
|
case kUpdateNow:
|
||||||
{
|
{
|
||||||
BMessenger messenger("application/x-vnd.Pogger");
|
BMessenger messenger("application/x-vnd.PoggerDaemon");
|
||||||
messenger.SendMessage(kUpdateSubscribed);
|
messenger.SendMessage(kUpdateSubscribed);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -108,7 +108,7 @@ DeskbarView::MessageReceived(BMessage* msg)
|
||||||
}
|
}
|
||||||
case kQuitPogger:
|
case kQuitPogger:
|
||||||
{
|
{
|
||||||
BMessenger messenger("application/x-vnd.Pogger");
|
BMessenger messenger("application/x-vnd.PoggerDaemon");
|
||||||
messenger.SendMessage(B_QUIT_REQUESTED);
|
messenger.SendMessage(B_QUIT_REQUESTED);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,7 +10,8 @@
|
||||||
|
|
||||||
#include <StorageKit.h>
|
#include <StorageKit.h>
|
||||||
|
|
||||||
#include "App.h"
|
#include "Daemon.h"
|
||||||
|
#include "Preferences.h"
|
||||||
#include "Util.h"
|
#include "Util.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -6,10 +6,10 @@
|
||||||
#include "Feed.h"
|
#include "Feed.h"
|
||||||
|
|
||||||
#include <File.h>
|
#include <File.h>
|
||||||
|
#include <FindDirectory.h>
|
||||||
|
|
||||||
#include <tinyxml2.h>
|
#include <tinyxml2.h>
|
||||||
|
|
||||||
#include "App.h"
|
|
||||||
#include "Entry.h"
|
#include "Entry.h"
|
||||||
#include "Util.h"
|
#include "Util.h"
|
||||||
|
|
||||||
|
|
|
@ -9,14 +9,16 @@
|
||||||
|
|
||||||
#include <Catalog.h>
|
#include <Catalog.h>
|
||||||
#include <Directory.h>
|
#include <Directory.h>
|
||||||
|
#include <FindDirectory.h>
|
||||||
#include <Message.h>
|
#include <Message.h>
|
||||||
#include <MessageRunner.h>
|
#include <MessageRunner.h>
|
||||||
#include <Notification.h>
|
#include <Notification.h>
|
||||||
#include <StringList.h>
|
#include <StringList.h>
|
||||||
|
|
||||||
#include "App.h"
|
#include "Daemon.h"
|
||||||
#include "AtomFeed.h"
|
#include "AtomFeed.h"
|
||||||
#include "Entry.h"
|
#include "Entry.h"
|
||||||
|
#include "LocalSource.h"
|
||||||
#include "RssFeed.h"
|
#include "RssFeed.h"
|
||||||
|
|
||||||
|
|
||||||
|
@ -71,7 +73,7 @@ FeedController::MessageReceived(BMessage* msg)
|
||||||
}
|
}
|
||||||
case kUpdateSubscribed:
|
case kUpdateSubscribed:
|
||||||
{
|
{
|
||||||
BStringList subFeeds = SubscribedFeeds();
|
BStringList subFeeds = LocalSource::Feeds();
|
||||||
fDownloadQueue->Add(subFeeds);
|
fDownloadQueue->Add(subFeeds);
|
||||||
|
|
||||||
_SendProgress();
|
_SendProgress();
|
||||||
|
@ -92,35 +94,6 @@ FeedController::MessageReceived(BMessage* msg)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
BStringList
|
|
||||||
FeedController::SubscribedFeeds()
|
|
||||||
{
|
|
||||||
BPath subPath;
|
|
||||||
find_directory(B_USER_SETTINGS_DIRECTORY, &subPath);
|
|
||||||
subPath.Append("Pogger");
|
|
||||||
subPath.Append("Subscriptions");
|
|
||||||
BDirectory subDir(subPath.Path());
|
|
||||||
if (subDir.InitCheck() == B_ENTRY_NOT_FOUND) {
|
|
||||||
subDir.CreateDirectory(subPath.Path(), &subDir);
|
|
||||||
|
|
||||||
subPath.Append("Haiku Project");
|
|
||||||
Feed defaultSub(BUrl("https://www.haiku-os.org/blog/index.xml"),
|
|
||||||
BEntry(subPath.Path()));
|
|
||||||
defaultSub.SetTitle("Haiku Project");
|
|
||||||
defaultSub.Filetize();
|
|
||||||
}
|
|
||||||
|
|
||||||
BEntry feedEntry;
|
|
||||||
BPath feedPath;
|
|
||||||
BStringList feeds;
|
|
||||||
|
|
||||||
while (subDir.GetNextEntry(&feedEntry) == B_OK
|
|
||||||
&& feedEntry.GetPath(&feedPath) == B_OK)
|
|
||||||
feeds.Add(feedPath.Path());
|
|
||||||
return feeds;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
FeedController::_SendProgress()
|
FeedController::_SendProgress()
|
||||||
{
|
{
|
||||||
|
|
|
@ -0,0 +1,8 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2021, Jaidyn Levesque <jadedctrl@teknik.io>
|
||||||
|
* All rights reserved. Distributed under the terms of the MIT license.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include "FeedSource.h"
|
||||||
|
|
|
@ -0,0 +1,22 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2021, Jaidyn Levesque <jadedctrl@teknik.io>
|
||||||
|
* All rights reserved. Distributed under the terms of the MIT license.
|
||||||
|
*/
|
||||||
|
#ifndef FEEDSOURCE_H
|
||||||
|
#define FEEDSOURCE_H
|
||||||
|
|
||||||
|
#include <StringList.h>
|
||||||
|
|
||||||
|
|
||||||
|
// Hierarchy: FeedSource → Feed → Entry
|
||||||
|
// TODO: RemoveFeed(), AddFeed(), etc.
|
||||||
|
class FeedSource {
|
||||||
|
public:
|
||||||
|
BStringList Feeds();
|
||||||
|
|
||||||
|
const char* name = "";
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif // FEEDSOURCE_H
|
||||||
|
|
|
@ -21,6 +21,7 @@
|
||||||
#include "FeedController.h"
|
#include "FeedController.h"
|
||||||
#include "FeedEditWindow.h"
|
#include "FeedEditWindow.h"
|
||||||
#include "FeedListItem.h"
|
#include "FeedListItem.h"
|
||||||
|
#include "LocalSource.h"
|
||||||
#include "Notifier.h"
|
#include "Notifier.h"
|
||||||
|
|
||||||
|
|
||||||
|
@ -219,7 +220,7 @@ FeedsView::_RemoveSelectedFeed()
|
||||||
void
|
void
|
||||||
FeedsView::_PopulateFeedList()
|
FeedsView::_PopulateFeedList()
|
||||||
{
|
{
|
||||||
BStringList feeds = FeedController::SubscribedFeeds();
|
BStringList feeds = LocalSource::Feeds();
|
||||||
int32 selected = fFeedsListView->CurrentSelection();
|
int32 selected = fFeedsListView->CurrentSelection();
|
||||||
|
|
||||||
for (int i = fFeedsListView->CountItems(); i >= 0; i--)
|
for (int i = fFeedsListView->CountItems(); i >= 0; i--)
|
||||||
|
|
|
@ -0,0 +1,44 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2021, Jaidyn Levesque <jadedctrl@teknik.io>
|
||||||
|
* All rights reserved. Distributed under the terms of the MIT license.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "LocalSource.h"
|
||||||
|
|
||||||
|
#include <Directory.h>
|
||||||
|
#include <Entry.h>
|
||||||
|
#include <FindDirectory.h>
|
||||||
|
#include <Path.h>
|
||||||
|
|
||||||
|
#include "Feed.h"
|
||||||
|
|
||||||
|
|
||||||
|
BStringList
|
||||||
|
LocalSource::Feeds()
|
||||||
|
{
|
||||||
|
BPath subPath;
|
||||||
|
find_directory(B_USER_SETTINGS_DIRECTORY, &subPath);
|
||||||
|
subPath.Append("Pogger");
|
||||||
|
subPath.Append("Subscriptions");
|
||||||
|
BDirectory subDir(subPath.Path());
|
||||||
|
if (subDir.InitCheck() == B_ENTRY_NOT_FOUND) {
|
||||||
|
subDir.CreateDirectory(subPath.Path(), &subDir);
|
||||||
|
|
||||||
|
subPath.Append("Haiku Project");
|
||||||
|
Feed defaultSub(BUrl("https://www.haiku-os.org/blog/index.xml"),
|
||||||
|
BEntry(subPath.Path()));
|
||||||
|
defaultSub.SetTitle("Haiku Project");
|
||||||
|
defaultSub.Filetize();
|
||||||
|
}
|
||||||
|
|
||||||
|
BEntry feedEntry;
|
||||||
|
BPath feedPath;
|
||||||
|
BStringList feeds;
|
||||||
|
|
||||||
|
while (subDir.GetNextEntry(&feedEntry) == B_OK
|
||||||
|
&& feedEntry.GetPath(&feedPath) == B_OK)
|
||||||
|
feeds.Add(feedPath.Path());
|
||||||
|
return feeds;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,19 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2021, Jaidyn Levesque <jadedctrl@teknik.io>
|
||||||
|
* All rights reserved. Distributed under the terms of the MIT license.
|
||||||
|
*/
|
||||||
|
#ifndef LOCALSOURCE_H
|
||||||
|
#define LOCALSOURCE_H
|
||||||
|
|
||||||
|
#include "FeedSource.h"
|
||||||
|
|
||||||
|
class LocalSource : public FeedSource {
|
||||||
|
public:
|
||||||
|
static BStringList Feeds();
|
||||||
|
|
||||||
|
const char* name = "Local";
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif // LOCALSOURCE_H
|
||||||
|
|
|
@ -40,6 +40,7 @@ MainWindow::~MainWindow()
|
||||||
{
|
{
|
||||||
((App*)be_app)->fPreferences->fMainWindowRect = ConvertToScreen(Bounds());
|
((App*)be_app)->fPreferences->fMainWindowRect = ConvertToScreen(Bounds());
|
||||||
((App*)be_app)->fPreferences->fTabSelection = fTabView->Selection();
|
((App*)be_app)->fPreferences->fTabSelection = fTabView->Selection();
|
||||||
|
be_app->PostMessage(B_QUIT_REQUESTED);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -88,14 +89,6 @@ MainWindow::MessageReceived(BMessage *msg)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool
|
|
||||||
MainWindow::QuitRequested()
|
|
||||||
{
|
|
||||||
Minimize(true);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
MainWindow::_InitInterface()
|
MainWindow::_InitInterface()
|
||||||
{
|
{
|
||||||
|
|
|
@ -18,7 +18,6 @@ public:
|
||||||
~MainWindow();
|
~MainWindow();
|
||||||
|
|
||||||
void MessageReceived(BMessage*);
|
void MessageReceived(BMessage*);
|
||||||
bool QuitRequested();
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void _InitInterface();
|
void _InitInterface();
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
|
|
||||||
resource app_signature "application/x-vnd.Pogger";
|
resource app_signature "application/x-vnd.Pogger";
|
||||||
|
|
||||||
resource app_flags B_SINGLE_LAUNCH | B_BACKGROUND_APP;
|
resource app_flags B_SINGLE_LAUNCH;
|
||||||
|
|
||||||
resource app_version {
|
resource app_version {
|
||||||
major = 0,
|
major = 0,
|
||||||
|
|
|
@ -98,6 +98,9 @@ Preferences::Save()
|
||||||
storage.AddInt32("tabSelection", fTabSelection);
|
storage.AddInt32("tabSelection", fTabSelection);
|
||||||
|
|
||||||
storage.Flatten(&file);
|
storage.Flatten(&file);
|
||||||
|
|
||||||
|
BMessenger toDaemon("application/x-vnd.PoggerDaemon");
|
||||||
|
toDaemon.SendMessage(kPreferencesUpdated);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -14,6 +14,7 @@ static const int64 HOUR_IN_MICROSECONDS = 3600000000;
|
||||||
|
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
|
kPreferencesUpdated = 'pfup',
|
||||||
kOpenAsHtml = 1,
|
kOpenAsHtml = 1,
|
||||||
kOpenAsUrl = 2
|
kOpenAsUrl = 2
|
||||||
};
|
};
|
||||||
|
|
|
@ -142,17 +142,8 @@ UpdatesView::_UpdateIntervalPreference()
|
||||||
int32 limit;
|
int32 limit;
|
||||||
fIntervalSlider->GetLimits(NULL, &limit);
|
fIntervalSlider->GetLimits(NULL, &limit);
|
||||||
int8 index = fIntervalSlider->Position() / (1/(float)limit);
|
int8 index = fIntervalSlider->Position() / (1/(float)limit);
|
||||||
int8 oldIndex = ((App*)be_app)->fPreferences->UpdateIntervalIndex();
|
|
||||||
|
|
||||||
((App*)be_app)->fPreferences->SetUpdateIntervalIndex(index);
|
((App*)be_app)->fPreferences->SetUpdateIntervalIndex(index);
|
||||||
|
|
||||||
if (oldIndex == 0)
|
|
||||||
((App*)be_app)->fUpdateRunner->SetCount(-1);
|
|
||||||
else if (index == 0)
|
|
||||||
((App*)be_app)->fUpdateRunner->SetCount(0);
|
|
||||||
|
|
||||||
((App*)be_app)->fUpdateRunner->SetInterval(
|
|
||||||
((App*)be_app)->fPreferences->UpdateInterval());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
Ŝarĝante…
Reference in New Issue