mirror of
https://github.com/abraunegg/onedrive
synced 2024-06-01 13:32:16 +02:00
Notification support via libnotify (#270)
* add external sources for (d)notify with README and license statements * add new logAndNotify function, make building a compile time option * use logAndNotify and main.d, make timeout message silent * update documentation for notification support * add command line switch --disable-notifications * add build-deps for libnotify in README.md
This commit is contained in:
parent
487cfab8d1
commit
cc6cbf5ac7
10
Makefile
10
Makefile
|
@ -1,5 +1,9 @@
|
||||||
DC ?= dmd
|
DC ?= dmd
|
||||||
DFLAGS += -w -g -ofonedrive -O -L-lcurl -L-lsqlite3 -L-ldl -J.
|
ifdef NOTIFICATIONS
|
||||||
|
DFLAGSNOTIFICATIONS ?= -version=NoPragma -version=NoGdk -version=Notifications \
|
||||||
|
-L-lgmodule-2.0 -L-lglib-2.0 -L-lnotify
|
||||||
|
endif
|
||||||
|
DFLAGS += -w -g -ofonedrive -O -L-lcurl -L-lsqlite3 $(DFLAGSNOTIFICATIONS) -L-ldl -J.
|
||||||
PREFIX ?= /usr/local
|
PREFIX ?= /usr/local
|
||||||
DOCDIR ?= $(PREFIX)/share/doc/onedrive
|
DOCDIR ?= $(PREFIX)/share/doc/onedrive
|
||||||
MANDIR ?= $(PREFIX)/share/man/man1
|
MANDIR ?= $(PREFIX)/share/man/man1
|
||||||
|
@ -26,6 +30,10 @@ SOURCES = \
|
||||||
src/util.d \
|
src/util.d \
|
||||||
src/progress.d
|
src/progress.d
|
||||||
|
|
||||||
|
ifdef NOTIFICATIONS
|
||||||
|
SOURCES += src/notifications/notify.d src/notifications/dnotify.d
|
||||||
|
endif
|
||||||
|
|
||||||
all: onedrive onedrive.service onedrive.1
|
all: onedrive onedrive.service onedrive.1
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
|
|
49
README.md
49
README.md
|
@ -8,6 +8,7 @@
|
||||||
* Support OneDrive for Business (part of Office 365)
|
* Support OneDrive for Business (part of Office 365)
|
||||||
* Shared folders (OneDrive Personal)
|
* Shared folders (OneDrive Personal)
|
||||||
* SharePoint / Office 365 Shared Libraries (refer to README.Office365.md to configure)
|
* SharePoint / Office 365 Shared Libraries (refer to README.Office365.md to configure)
|
||||||
|
* Notifications
|
||||||
|
|
||||||
### What's missing:
|
### What's missing:
|
||||||
* While local changes are uploaded right away, remote changes are delayed
|
* While local changes are uploaded right away, remote changes are delayed
|
||||||
|
@ -26,6 +27,10 @@ sudo apt install libcurl4-openssl-dev
|
||||||
sudo apt install libsqlite3-dev
|
sudo apt install libsqlite3-dev
|
||||||
curl -fsS https://dlang.org/install.sh | bash -s dmd
|
curl -fsS https://dlang.org/install.sh | bash -s dmd
|
||||||
```
|
```
|
||||||
|
For notifications the following is necessary:
|
||||||
|
```
|
||||||
|
sudo apt install libnotify-dev
|
||||||
|
```
|
||||||
|
|
||||||
### Dependencies: Ubuntu - i386 / i686
|
### Dependencies: Ubuntu - i386 / i686
|
||||||
**Note:** Validated with `Linux ubuntu-i386-vm 4.13.0-36-generic #40~16.04.1-Ubuntu SMP Fri Feb 16 23:26:51 UTC 2018 i686 i686 i686 GNU/Linux` and DMD 2.081.1
|
**Note:** Validated with `Linux ubuntu-i386-vm 4.13.0-36-generic #40~16.04.1-Ubuntu SMP Fri Feb 16 23:26:51 UTC 2018 i686 i686 i686 GNU/Linux` and DMD 2.081.1
|
||||||
|
@ -35,6 +40,10 @@ sudo apt install libcurl4-openssl-dev
|
||||||
sudo apt install libsqlite3-dev
|
sudo apt install libsqlite3-dev
|
||||||
curl -fsS https://dlang.org/install.sh | bash -s dmd
|
curl -fsS https://dlang.org/install.sh | bash -s dmd
|
||||||
```
|
```
|
||||||
|
For notifications the following is necessary:
|
||||||
|
```
|
||||||
|
sudo apt install libnotify-dev
|
||||||
|
```
|
||||||
|
|
||||||
### Dependencies: Debian - i386 / i686
|
### Dependencies: Debian - i386 / i686
|
||||||
**Note:** Validated with `Linux debian-i386 4.9.0-7-686-pae #1 SMP Debian 4.9.110-1 (2018-07-05) i686 GNU/Linux` and LDC - the LLVM D compiler (1.8.0).
|
**Note:** Validated with `Linux debian-i386 4.9.0-7-686-pae #1 SMP Debian 4.9.110-1 (2018-07-05) i686 GNU/Linux` and LDC - the LLVM D compiler (1.8.0).
|
||||||
|
@ -56,6 +65,10 @@ wget http://ftp.us.debian.org/debian/pool/main/l/llvm-toolchain-5.0/libllvm5.0_5
|
||||||
wget http://ftp.us.debian.org/debian/pool/main/n/ncurses/libtinfo6_6.1+20180714-1_i386.deb
|
wget http://ftp.us.debian.org/debian/pool/main/n/ncurses/libtinfo6_6.1+20180714-1_i386.deb
|
||||||
sudo dpkg -i ./*.deb
|
sudo dpkg -i ./*.deb
|
||||||
```
|
```
|
||||||
|
For notifications the following is necessary:
|
||||||
|
```
|
||||||
|
sudo apt install libnotify-dev
|
||||||
|
```
|
||||||
|
|
||||||
### Dependencies: Fedora < Version 18 / CentOS / RHEL
|
### Dependencies: Fedora < Version 18 / CentOS / RHEL
|
||||||
```
|
```
|
||||||
|
@ -64,6 +77,10 @@ sudo yum install libcurl-devel
|
||||||
sudo yum install sqlite-devel
|
sudo yum install sqlite-devel
|
||||||
curl -fsS https://dlang.org/install.sh | bash -s dmd
|
curl -fsS https://dlang.org/install.sh | bash -s dmd
|
||||||
```
|
```
|
||||||
|
For notifications the following is necessary:
|
||||||
|
```
|
||||||
|
sudo yum install libnotify-devel
|
||||||
|
```
|
||||||
|
|
||||||
### Dependencies: Fedora > Version 18
|
### Dependencies: Fedora > Version 18
|
||||||
```
|
```
|
||||||
|
@ -72,11 +89,19 @@ sudo dnf install libcurl-devel
|
||||||
sudo dnf install sqlite-devel
|
sudo dnf install sqlite-devel
|
||||||
curl -fsS https://dlang.org/install.sh | bash -s dmd
|
curl -fsS https://dlang.org/install.sh | bash -s dmd
|
||||||
```
|
```
|
||||||
|
For notifications the following is necessary:
|
||||||
|
```
|
||||||
|
sudo yum install libnotify-devel
|
||||||
|
```
|
||||||
|
|
||||||
### Dependencies: Arch Linux
|
### Dependencies: Arch Linux
|
||||||
```
|
```
|
||||||
sudo pacman -S curl sqlite dmd
|
sudo pacman -S curl sqlite dmd
|
||||||
```
|
```
|
||||||
|
For notifications the following is necessary:
|
||||||
|
```
|
||||||
|
sudo pacman -S libnotify
|
||||||
|
```
|
||||||
|
|
||||||
### Dependencies: Raspbian (ARMHF)
|
### Dependencies: Raspbian (ARMHF)
|
||||||
```
|
```
|
||||||
|
@ -85,6 +110,10 @@ sudo apt-get install libsqlite3-dev
|
||||||
wget https://github.com/ldc-developers/ldc/releases/download/v1.11.0/ldc2-1.11.0-linux-armhf.tar.xz
|
wget https://github.com/ldc-developers/ldc/releases/download/v1.11.0/ldc2-1.11.0-linux-armhf.tar.xz
|
||||||
tar -xvf ldc2-1.11.0-linux-armhf.tar.xz
|
tar -xvf ldc2-1.11.0-linux-armhf.tar.xz
|
||||||
```
|
```
|
||||||
|
For notifications the following is necessary:
|
||||||
|
```
|
||||||
|
sudo apt install libnotify-dev
|
||||||
|
```
|
||||||
|
|
||||||
### Dependencies: Debian (ARM64)
|
### Dependencies: Debian (ARM64)
|
||||||
```
|
```
|
||||||
|
@ -93,6 +122,10 @@ sudo apt-get install libsqlite3-dev
|
||||||
wget https://github.com/ldc-developers/ldc/releases/download/v1.11.0/ldc2-1.11.0-linux-aarch64.tar.xz
|
wget https://github.com/ldc-developers/ldc/releases/download/v1.11.0/ldc2-1.11.0-linux-aarch64.tar.xz
|
||||||
tar -xvf ldc2-1.11.0-linux-aarch64.tar.xz
|
tar -xvf ldc2-1.11.0-linux-aarch64.tar.xz
|
||||||
```
|
```
|
||||||
|
For notifications the following is necessary:
|
||||||
|
```
|
||||||
|
sudo apt install libnotify-dev
|
||||||
|
```
|
||||||
|
|
||||||
### Dependencies: Gentoo
|
### Dependencies: Gentoo
|
||||||
```
|
```
|
||||||
|
@ -101,11 +134,20 @@ sudo layman -a dlang
|
||||||
```
|
```
|
||||||
Add ebuild from contrib/gentoo to a local overlay to use.
|
Add ebuild from contrib/gentoo to a local overlay to use.
|
||||||
|
|
||||||
|
For notifications the following is necessary:
|
||||||
|
```
|
||||||
|
sudo emerge x11-libs/libnotify
|
||||||
|
```
|
||||||
|
|
||||||
### Dependencies: OpenSuSE Leap 15.0
|
### Dependencies: OpenSuSE Leap 15.0
|
||||||
```
|
```
|
||||||
sudo zypper addrepo --check --refresh --name "D" http://download.opensuse.org/repositories/devel:/languages:/D/openSUSE_Leap_15.0/devel:languages:D.repo
|
sudo zypper addrepo --check --refresh --name "D" http://download.opensuse.org/repositories/devel:/languages:/D/openSUSE_Leap_15.0/devel:languages:D.repo
|
||||||
sudo zypper install git libcurl-devel sqlite3-devel D:dmd D:libphobos2-0_81 D:phobos-devel D:phobos-devel-static
|
sudo zypper install git libcurl-devel sqlite3-devel D:dmd D:libphobos2-0_81 D:phobos-devel D:phobos-devel-static
|
||||||
```
|
```
|
||||||
|
For notifications the following is necessary:
|
||||||
|
```
|
||||||
|
sudo zypper install libnotify-devel
|
||||||
|
```
|
||||||
|
|
||||||
## Compilation & Installation
|
## Compilation & Installation
|
||||||
### Building using DMD Reference Compiler:
|
### Building using DMD Reference Compiler:
|
||||||
|
@ -126,6 +168,13 @@ make
|
||||||
sudo make install
|
sudo make install
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### Build options ###
|
||||||
|
By passing `NOTIFICATIONS=1` to the `make` call, notifications via
|
||||||
|
libnotify are enabled. Necessary libraries are
|
||||||
|
`gmodule-2.0`, `glib-2.0`, and `notify`. If these libraries are
|
||||||
|
named differently on the build system, the make variable
|
||||||
|
`DFLAGSNOTIFICATIONS` can be adjusted.
|
||||||
|
|
||||||
### Building using a different compiler (for example [LDC](https://wiki.dlang.org/LDC)):
|
### Building using a different compiler (for example [LDC](https://wiki.dlang.org/LDC)):
|
||||||
#### Debian - i386 / i686
|
#### Debian - i386 / i686
|
||||||
```
|
```
|
||||||
|
|
|
@ -27,6 +27,9 @@ Debug OneDrive HTTPS communication.
|
||||||
\fB\-d \-\-download\-only\fP
|
\fB\-d \-\-download\-only\fP
|
||||||
Only download remote changes
|
Only download remote changes
|
||||||
.TP
|
.TP
|
||||||
|
\fB\-\-disable\-notifications\fP
|
||||||
|
Do not use desktop notifications in monitor mode
|
||||||
|
.TP
|
||||||
\fB\-\-disable\-upload\-validation\fP
|
\fB\-\-disable\-upload\-validation\fP
|
||||||
Disable upload validation when uploading to OneDrive
|
Disable upload validation when uploading to OneDrive
|
||||||
.TP
|
.TP
|
||||||
|
@ -191,6 +194,15 @@ All logfiles will be in the format of \fB%username%.onedrive.log\fP,
|
||||||
where \fB%username%\fP represents the user who ran the client.
|
where \fB%username%\fP represents the user who ran the client.
|
||||||
|
|
||||||
|
|
||||||
|
.SH NOTIFICATIONS
|
||||||
|
|
||||||
|
If OneDrive has been compiled with support for notifications, a running
|
||||||
|
\fBonedrive\fP in monitor mode will send notifications about
|
||||||
|
initialization and errors via libnotify to the dbus.
|
||||||
|
|
||||||
|
Note that this does not work if \fBonedrive\fP is started as root
|
||||||
|
for a user via the \fBonedrive@<username>\fP service.
|
||||||
|
|
||||||
.SH SEE ALSO
|
.SH SEE ALSO
|
||||||
|
|
||||||
Further examples and documentation is available in
|
Further examples and documentation is available in
|
||||||
|
|
43
src/log.d
43
src/log.d
|
@ -2,13 +2,19 @@ import std.stdio;
|
||||||
import std.file;
|
import std.file;
|
||||||
import std.datetime;
|
import std.datetime;
|
||||||
import std.process;
|
import std.process;
|
||||||
|
import std.conv;
|
||||||
import core.sys.posix.pwd, core.sys.posix.unistd, core.stdc.string : strlen;
|
import core.sys.posix.pwd, core.sys.posix.unistd, core.stdc.string : strlen;
|
||||||
import std.algorithm : splitter;
|
import std.algorithm : splitter;
|
||||||
|
version(Notifications) {
|
||||||
|
import dnotify;
|
||||||
|
}
|
||||||
|
|
||||||
// enable verbose logging
|
// enable verbose logging
|
||||||
bool verbose;
|
bool verbose;
|
||||||
bool writeLogFile = false;
|
bool writeLogFile = false;
|
||||||
|
|
||||||
|
private bool doNotifications;
|
||||||
|
|
||||||
// shared string variable for username
|
// shared string variable for username
|
||||||
string username;
|
string username;
|
||||||
string logFilePath;
|
string logFilePath;
|
||||||
|
@ -33,6 +39,11 @@ void init(string logDir)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void setNotifications(bool value)
|
||||||
|
{
|
||||||
|
doNotifications = value;
|
||||||
|
}
|
||||||
|
|
||||||
void log(T...)(T args)
|
void log(T...)(T args)
|
||||||
{
|
{
|
||||||
writeln(args);
|
writeln(args);
|
||||||
|
@ -42,6 +53,12 @@ void log(T...)(T args)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void logAndNotify(T...)(T args)
|
||||||
|
{
|
||||||
|
notify(args);
|
||||||
|
log(args);
|
||||||
|
}
|
||||||
|
|
||||||
void fileOnly(T...)(T args)
|
void fileOnly(T...)(T args)
|
||||||
{
|
{
|
||||||
if(writeLogFile){
|
if(writeLogFile){
|
||||||
|
@ -70,6 +87,32 @@ void error(T...)(T args)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void errorAndNotify(T...)(T args)
|
||||||
|
{
|
||||||
|
notify(args);
|
||||||
|
error(args);
|
||||||
|
}
|
||||||
|
|
||||||
|
void notify(T...)(T args)
|
||||||
|
{
|
||||||
|
version(Notifications) {
|
||||||
|
if (doNotifications) {
|
||||||
|
string result;
|
||||||
|
foreach (index, arg; args) {
|
||||||
|
result ~= to!string(arg);
|
||||||
|
if (index != args.length - 1)
|
||||||
|
result ~= " ";
|
||||||
|
}
|
||||||
|
auto n = new Notification("OneDrive", result, "IGNORED");
|
||||||
|
try {
|
||||||
|
n.show();
|
||||||
|
} catch (Throwable e) {
|
||||||
|
vlog("Got exception from showing notification: ", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void logfileWriteLine(T...)(T args)
|
private void logfileWriteLine(T...)(T args)
|
||||||
{
|
{
|
||||||
// Write to log file
|
// Write to log file
|
||||||
|
|
28
src/main.d
28
src/main.d
|
@ -90,6 +90,8 @@ int main(string[] args)
|
||||||
bool disableUploadValidation = false;
|
bool disableUploadValidation = false;
|
||||||
// SharePoint / Office 365 Shared Library name to query
|
// SharePoint / Office 365 Shared Library name to query
|
||||||
string o365SharedLibraryName;
|
string o365SharedLibraryName;
|
||||||
|
// Do not use notifications in monitor mode
|
||||||
|
bool disableNotifications = false;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
auto opt = getopt(
|
auto opt = getopt(
|
||||||
|
@ -101,6 +103,7 @@ int main(string[] args)
|
||||||
"create-directory", "Create a directory on OneDrive - no sync will be performed.", &createDirectory,
|
"create-directory", "Create a directory on OneDrive - no sync will be performed.", &createDirectory,
|
||||||
"destination-directory", "Destination directory for renamed or move on OneDrive - no sync will be performed.", &destinationDirectory,
|
"destination-directory", "Destination directory for renamed or move on OneDrive - no sync will be performed.", &destinationDirectory,
|
||||||
"debug-https", "Debug OneDrive HTTPS communication.", &debugHttp,
|
"debug-https", "Debug OneDrive HTTPS communication.", &debugHttp,
|
||||||
|
"disable-notifications", "Do not use desktop notifications in monitor mode.", &disableNotifications,
|
||||||
"download-only|d", "Only download remote changes", &downloadOnly,
|
"download-only|d", "Only download remote changes", &downloadOnly,
|
||||||
"disable-upload-validation", "Disable upload validation when uploading to OneDrive", &disableUploadValidation,
|
"disable-upload-validation", "Disable upload validation when uploading to OneDrive", &disableUploadValidation,
|
||||||
"enable-logging", "Enable client activity to a separate log file", &enableLogFile,
|
"enable-logging", "Enable client activity to a separate log file", &enableLogFile,
|
||||||
|
@ -159,6 +162,9 @@ int main(string[] args)
|
||||||
log.init(logDir);
|
log.init(logDir);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Configure whether notifications are used
|
||||||
|
log.setNotifications(monitor && !disableNotifications);
|
||||||
|
|
||||||
// command line parameters override the config
|
// command line parameters override the config
|
||||||
if (syncDirName) cfg.setValue("sync_dir", syncDirName.expandTilde().absolutePath());
|
if (syncDirName) cfg.setValue("sync_dir", syncDirName.expandTilde().absolutePath());
|
||||||
if (skipSymlinks) cfg.setValue("skip_symlinks", "true");
|
if (skipSymlinks) cfg.setValue("skip_symlinks", "true");
|
||||||
|
@ -166,7 +172,7 @@ int main(string[] args)
|
||||||
// upgrades
|
// upgrades
|
||||||
if (exists(configDirName ~ "/items.db")) {
|
if (exists(configDirName ~ "/items.db")) {
|
||||||
remove(configDirName ~ "/items.db");
|
remove(configDirName ~ "/items.db");
|
||||||
log.log("Database schema changed, resync needed");
|
log.logAndNotify("Database schema changed, resync needed");
|
||||||
resync = true;
|
resync = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -257,7 +263,7 @@ int main(string[] args)
|
||||||
selectiveSync.setMask(cfg.getValue("skip_file"));
|
selectiveSync.setMask(cfg.getValue("skip_file"));
|
||||||
|
|
||||||
// Initialise the sync engine
|
// Initialise the sync engine
|
||||||
log.log("Initializing the Synchronization Engine ...");
|
log.logAndNotify("Initializing the Synchronization Engine ...");
|
||||||
auto sync = new SyncEngine(cfg, onedrive, itemdb, selectiveSync);
|
auto sync = new SyncEngine(cfg, onedrive, itemdb, selectiveSync);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
@ -283,7 +289,7 @@ int main(string[] args)
|
||||||
if (checkMount) {
|
if (checkMount) {
|
||||||
// we were asked to check the mounts
|
// we were asked to check the mounts
|
||||||
if (exists(syncDir ~ "/.nosync")) {
|
if (exists(syncDir ~ "/.nosync")) {
|
||||||
log.log("\nERROR: .nosync file found. Aborting synchronization process to safeguard data.");
|
log.logAndNotify("ERROR: .nosync file found. Aborting synchronization process to safeguard data.");
|
||||||
onedrive.http.shutdown();
|
onedrive.http.shutdown();
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
|
@ -324,7 +330,7 @@ int main(string[] args)
|
||||||
// Does the directory we want to sync actually exist?
|
// Does the directory we want to sync actually exist?
|
||||||
if (!exists(singleDirectory)){
|
if (!exists(singleDirectory)){
|
||||||
// the requested directory does not exist ..
|
// the requested directory does not exist ..
|
||||||
log.log("The requested local directory does not exist. Please check ~/OneDrive/ for requested path");
|
log.logAndNotify("ERROR: The requested local directory does not exist. Please check ~/OneDrive/ for requested path");
|
||||||
onedrive.http.shutdown();
|
onedrive.http.shutdown();
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
|
@ -336,7 +342,7 @@ int main(string[] args)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (monitor) {
|
if (monitor) {
|
||||||
log.log("Initializing monitor ...");
|
log.logAndNotify("Initializing monitor ...");
|
||||||
log.log("OneDrive monitor interval (seconds): ", to!long(cfg.getValue("monitor_interval")));
|
log.log("OneDrive monitor interval (seconds): ", to!long(cfg.getValue("monitor_interval")));
|
||||||
Monitor m = new Monitor(selectiveSync);
|
Monitor m = new Monitor(selectiveSync);
|
||||||
m.onDirCreated = delegate(string path) {
|
m.onDirCreated = delegate(string path) {
|
||||||
|
@ -344,7 +350,7 @@ int main(string[] args)
|
||||||
try {
|
try {
|
||||||
sync.scanForDifferences(path);
|
sync.scanForDifferences(path);
|
||||||
} catch(Exception e) {
|
} catch(Exception e) {
|
||||||
log.log(e.msg);
|
log.logAndNotify(e.msg);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
m.onFileChanged = delegate(string path) {
|
m.onFileChanged = delegate(string path) {
|
||||||
|
@ -352,7 +358,7 @@ int main(string[] args)
|
||||||
try {
|
try {
|
||||||
sync.scanForDifferences(path);
|
sync.scanForDifferences(path);
|
||||||
} catch(Exception e) {
|
} catch(Exception e) {
|
||||||
log.log(e.msg);
|
log.logAndNotify(e.msg);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
m.onDelete = delegate(string path) {
|
m.onDelete = delegate(string path) {
|
||||||
|
@ -360,7 +366,7 @@ int main(string[] args)
|
||||||
try {
|
try {
|
||||||
sync.deleteByPath(path);
|
sync.deleteByPath(path);
|
||||||
} catch(Exception e) {
|
} catch(Exception e) {
|
||||||
log.log(e.msg);
|
log.logAndNotify(e.msg);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
m.onMove = delegate(string from, string to) {
|
m.onMove = delegate(string from, string to) {
|
||||||
|
@ -368,7 +374,7 @@ int main(string[] args)
|
||||||
try {
|
try {
|
||||||
sync.uploadMoveItem(from, to);
|
sync.uploadMoveItem(from, to);
|
||||||
} catch(Exception e) {
|
} catch(Exception e) {
|
||||||
log.log(e.msg);
|
log.logAndNotify(e.msg);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
// initialise the monitor class
|
// initialise the monitor class
|
||||||
|
@ -395,6 +401,7 @@ int main(string[] args)
|
||||||
// TODO better check of type of exception from Curl
|
// TODO better check of type of exception from Curl
|
||||||
// could be either timeout of operation of connection error
|
// could be either timeout of operation of connection error
|
||||||
// No network connection to OneDrive Service
|
// No network connection to OneDrive Service
|
||||||
|
// Don't overload notifications
|
||||||
log.log("No network connection to Microsoft OneDrive Service, skipping sync");
|
log.log("No network connection to Microsoft OneDrive Service, skipping sync");
|
||||||
}
|
}
|
||||||
// performSync complete, set lastCheckTime to current time
|
// performSync complete, set lastCheckTime to current time
|
||||||
|
@ -502,7 +509,8 @@ void performSync(SyncEngine sync, string singleDirectory, bool downloadOnly, boo
|
||||||
count = -1;
|
count = -1;
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
if (++count == 3) throw e;
|
if (++count == 3) throw e;
|
||||||
else log.log(e.msg);
|
else log.logAndNotify(e.msg);
|
||||||
}
|
}
|
||||||
} while (count != -1);
|
} while (count != -1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
10
src/notifications/README
Normal file
10
src/notifications/README
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
The files in this directory have been obtained form the following places:
|
||||||
|
|
||||||
|
dnotify.d
|
||||||
|
https://github.com/Dav1dde/dnotify/blob/master/dnotify.d
|
||||||
|
License: Creative Commons Zro 1.0 Universal
|
||||||
|
see https://github.com/Dav1dde/dnotify/blob/master/LICENSE
|
||||||
|
|
||||||
|
notify.d
|
||||||
|
https://github.com/D-Programming-Deimos/libnotify/blob/master/deimos/notify/notify.d
|
||||||
|
License: GPL 2.1 or upwards, see file
|
309
src/notifications/dnotify.d
Normal file
309
src/notifications/dnotify.d
Normal file
|
@ -0,0 +1,309 @@
|
||||||
|
module dnotify;
|
||||||
|
|
||||||
|
private {
|
||||||
|
import std.string : toStringz;
|
||||||
|
import std.conv : to;
|
||||||
|
import std.traits : isPointer, isArray;
|
||||||
|
import std.variant : Variant;
|
||||||
|
import std.array : appender;
|
||||||
|
|
||||||
|
import deimos.notify.notify;
|
||||||
|
}
|
||||||
|
|
||||||
|
public import deimos.notify.notify : NOTIFY_EXPIRES_DEFAULT, NOTIFY_EXPIRES_NEVER,
|
||||||
|
NotifyUrgency;
|
||||||
|
|
||||||
|
|
||||||
|
version(NoPragma) {
|
||||||
|
} else {
|
||||||
|
pragma(lib, "notify");
|
||||||
|
pragma(lib, "gmodule");
|
||||||
|
pragma(lib, "glib-2.0");
|
||||||
|
}
|
||||||
|
|
||||||
|
extern (C) {
|
||||||
|
private void g_free(void* mem);
|
||||||
|
private void g_list_free(GList* glist);
|
||||||
|
}
|
||||||
|
|
||||||
|
version(NoGdk) {
|
||||||
|
} else {
|
||||||
|
version(NoPragma) {
|
||||||
|
} else {
|
||||||
|
pragma(lib, "gdk_pixbuf");
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
extern (C) {
|
||||||
|
GdkPixbuf* gdk_pixbuf_new_from_file(const(char)* filename, GError **error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class NotificationError : Exception {
|
||||||
|
string message;
|
||||||
|
GError* gerror;
|
||||||
|
|
||||||
|
this(GError* gerror) {
|
||||||
|
this.message = to!(string)(gerror.message);
|
||||||
|
this.gerror = gerror;
|
||||||
|
|
||||||
|
super(this.message);
|
||||||
|
}
|
||||||
|
|
||||||
|
this(string message) {
|
||||||
|
this.message = message;
|
||||||
|
|
||||||
|
super(message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void init(in char[] name) {
|
||||||
|
notify_init(name.toStringz());
|
||||||
|
}
|
||||||
|
|
||||||
|
alias notify_is_initted is_initted;
|
||||||
|
alias notify_uninit uninit;
|
||||||
|
|
||||||
|
static this() {
|
||||||
|
init(__FILE__);
|
||||||
|
}
|
||||||
|
|
||||||
|
static ~this() {
|
||||||
|
uninit();
|
||||||
|
}
|
||||||
|
|
||||||
|
string get_app_name() {
|
||||||
|
return to!(string)(notify_get_app_name());
|
||||||
|
}
|
||||||
|
|
||||||
|
void set_app_name(in char[] app_name) {
|
||||||
|
notify_set_app_name(app_name.toStringz());
|
||||||
|
}
|
||||||
|
|
||||||
|
string[] get_server_caps() {
|
||||||
|
auto result = appender!(string[])();
|
||||||
|
|
||||||
|
GList* list = notify_get_server_caps();
|
||||||
|
if(list !is null) {
|
||||||
|
for(GList* c = list; c !is null; c = c.next) {
|
||||||
|
result.put(to!(string)(cast(char*)c.data));
|
||||||
|
g_free(c.data);
|
||||||
|
}
|
||||||
|
|
||||||
|
g_list_free(list);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result.data;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct ServerInfo {
|
||||||
|
string name;
|
||||||
|
string vendor;
|
||||||
|
string version_;
|
||||||
|
string spec_version;
|
||||||
|
}
|
||||||
|
|
||||||
|
ServerInfo get_server_info() {
|
||||||
|
char* name;
|
||||||
|
char* vendor;
|
||||||
|
char* version_;
|
||||||
|
char* spec_version;
|
||||||
|
notify_get_server_info(&name, &vendor, &version_, &spec_version);
|
||||||
|
|
||||||
|
scope(exit) {
|
||||||
|
g_free(name);
|
||||||
|
g_free(vendor);
|
||||||
|
g_free(version_);
|
||||||
|
g_free(spec_version);
|
||||||
|
}
|
||||||
|
|
||||||
|
return ServerInfo(to!string(name), to!string(vendor), to!string(version_), to!string(spec_version));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
struct Action {
|
||||||
|
const(char[]) id;
|
||||||
|
const(char[]) label;
|
||||||
|
NotifyActionCallback callback;
|
||||||
|
void* user_ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
class Notification {
|
||||||
|
NotifyNotification* notify_notification;
|
||||||
|
|
||||||
|
const(char)[] summary;
|
||||||
|
const(char)[] body_;
|
||||||
|
const(char)[] icon;
|
||||||
|
|
||||||
|
bool closed = true;
|
||||||
|
|
||||||
|
private int _timeout = NOTIFY_EXPIRES_DEFAULT;
|
||||||
|
const(char)[] _category;
|
||||||
|
NotifyUrgency _urgency;
|
||||||
|
GdkPixbuf* _image;
|
||||||
|
Variant[const(char)[]] _hints;
|
||||||
|
const(char)[] _app_name;
|
||||||
|
Action[] _actions;
|
||||||
|
|
||||||
|
this(in char[] summary, in char[] body_, in char[] icon="")
|
||||||
|
in { assert(is_initted(), "call dnotify.init() before using Notification"); }
|
||||||
|
body {
|
||||||
|
this.summary = summary;
|
||||||
|
this.body_ = body_;
|
||||||
|
this.icon = icon;
|
||||||
|
notify_notification = notify_notification_new(summary.toStringz(), body_.toStringz(), icon.toStringz());
|
||||||
|
}
|
||||||
|
|
||||||
|
bool update(in char[] summary, in char[] body_, in char[] icon="") {
|
||||||
|
this.summary = summary;
|
||||||
|
this.body_ = body_;
|
||||||
|
this.icon = icon;
|
||||||
|
return notify_notification_update(notify_notification, summary.toStringz(), body_.toStringz(), icon.toStringz());
|
||||||
|
}
|
||||||
|
|
||||||
|
void show() {
|
||||||
|
GError* ge;
|
||||||
|
|
||||||
|
if(!notify_notification_show(notify_notification, &ge)) {
|
||||||
|
throw new NotificationError(ge);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@property int timeout() { return _timeout; }
|
||||||
|
@property void timeout(int timeout) {
|
||||||
|
this._timeout = timeout;
|
||||||
|
notify_notification_set_timeout(notify_notification, timeout);
|
||||||
|
}
|
||||||
|
|
||||||
|
@property const(char[]) category() { return _category; }
|
||||||
|
@property void category(in char[] category) {
|
||||||
|
this._category = category;
|
||||||
|
notify_notification_set_category(notify_notification, category.toStringz());
|
||||||
|
}
|
||||||
|
|
||||||
|
@property NotifyUrgency urgency() { return _urgency; }
|
||||||
|
@property void urgency(NotifyUrgency urgency) {
|
||||||
|
this._urgency = urgency;
|
||||||
|
notify_notification_set_urgency(notify_notification, urgency);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void set_image(GdkPixbuf* pixbuf) {
|
||||||
|
notify_notification_set_image_from_pixbuf(notify_notification, pixbuf);
|
||||||
|
//_image = pixbuf;
|
||||||
|
}
|
||||||
|
|
||||||
|
version(NoGdk) {
|
||||||
|
} else {
|
||||||
|
void set_image(in char[] filename) {
|
||||||
|
GError* ge;
|
||||||
|
// TODO: free pixbuf
|
||||||
|
GdkPixbuf* pixbuf = gdk_pixbuf_new_from_file(filename.toStringz(), &ge);
|
||||||
|
|
||||||
|
if(pixbuf is null) {
|
||||||
|
if(ge is null) {
|
||||||
|
throw new NotificationError("Unable to load file: " ~ filename.idup);
|
||||||
|
} else {
|
||||||
|
throw new NotificationError(ge);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
assert(notify_notification !is null);
|
||||||
|
notify_notification_set_image_from_pixbuf(notify_notification, pixbuf); // TODO: fix segfault
|
||||||
|
//_image = pixbuf;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@property GdkPixbuf* image() { return _image; }
|
||||||
|
|
||||||
|
// using deprecated set_hint_* functions (GVariant is an opaque structure, which needs the glib)
|
||||||
|
void set_hint(T)(in char[] key, T value) {
|
||||||
|
static if(is(T == int)) {
|
||||||
|
notify_notification_set_hint_int32(notify_notification, key, value);
|
||||||
|
} else static if(is(T == uint)) {
|
||||||
|
notify_notification_set_hint_uint32(notify_notification, key, value);
|
||||||
|
} else static if(is(T == double)) {
|
||||||
|
notify_notification_set_hint_double(notify_notification, key, value);
|
||||||
|
} else static if(is(T : const(char)[])) {
|
||||||
|
notify_notification_set_hint_string(notify_notification, key, value.toStringz());
|
||||||
|
} else static if(is(T == ubyte)) {
|
||||||
|
notify_notification_set_hint_byte(notify_notification, key, value);
|
||||||
|
} else static if(is(T == ubyte[])) {
|
||||||
|
notify_notification_set_hint_byte_array(notify_notification, key, value.ptr, value.length);
|
||||||
|
} else {
|
||||||
|
static assert(false, "unsupported value for Notification.set_hint");
|
||||||
|
}
|
||||||
|
|
||||||
|
_hints[key] = Variant(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
// unset hint?
|
||||||
|
|
||||||
|
Variant get_hint(in char[] key) {
|
||||||
|
return _hints[key];
|
||||||
|
}
|
||||||
|
|
||||||
|
@property const(char)[] app_name() { return _app_name; }
|
||||||
|
@property void app_name(in char[] name) {
|
||||||
|
this._app_name = app_name;
|
||||||
|
notify_notification_set_app_name(notify_notification, app_name.toStringz());
|
||||||
|
}
|
||||||
|
|
||||||
|
void add_action(T)(in char[] action, in char[] label, NotifyActionCallback callback, T user_data) {
|
||||||
|
static if(isPointer!T) {
|
||||||
|
void* user_ptr = cast(void*)user_data;
|
||||||
|
} else static if(isArray!T) {
|
||||||
|
void* user_ptr = cast(void*)user_data.ptr;
|
||||||
|
} else {
|
||||||
|
void* user_ptr = cast(void*)&user_data;
|
||||||
|
}
|
||||||
|
|
||||||
|
notify_notification_add_action(notify_notification, action.toStringz(), label.toStringz(),
|
||||||
|
callback, user_ptr, null);
|
||||||
|
|
||||||
|
_actions ~= Action(action, label, callback, user_ptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
void add_action()(Action action) {
|
||||||
|
notify_notification_add_action(notify_notification, action.id.toStringz(), action.label.toStringz(),
|
||||||
|
action.callback, action.user_ptr, null);
|
||||||
|
|
||||||
|
_actions ~= action;
|
||||||
|
}
|
||||||
|
|
||||||
|
@property Action[] actions() { return _actions; }
|
||||||
|
|
||||||
|
void clear_actions() {
|
||||||
|
notify_notification_clear_actions(notify_notification);
|
||||||
|
}
|
||||||
|
|
||||||
|
void close() {
|
||||||
|
GError* ge;
|
||||||
|
|
||||||
|
if(!notify_notification_close(notify_notification, &ge)) {
|
||||||
|
throw new NotificationError(ge);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@property int closed_reason() {
|
||||||
|
return notify_notification_get_closed_reason(notify_notification);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
version(TestMain) {
|
||||||
|
import std.stdio;
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
writeln(get_app_name());
|
||||||
|
set_app_name("bla");
|
||||||
|
writeln(get_app_name());
|
||||||
|
writeln(get_server_caps());
|
||||||
|
writeln(get_server_info());
|
||||||
|
|
||||||
|
auto n = new Notification("foo", "bar", "notification-message-im");
|
||||||
|
n.timeout = 3;
|
||||||
|
n.show();
|
||||||
|
}
|
||||||
|
}
|
195
src/notifications/notify.d
Normal file
195
src/notifications/notify.d
Normal file
|
@ -0,0 +1,195 @@
|
||||||
|
/**
|
||||||
|
* Copyright (C) 2004-2006 Christian Hammond
|
||||||
|
* Copyright (C) 2010 Red Hat, Inc.
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2.1 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the
|
||||||
|
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||||
|
* Boston, MA 02111-1307, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
module deimos.notify.notify;
|
||||||
|
|
||||||
|
|
||||||
|
enum NOTIFY_VERSION_MAJOR = 0;
|
||||||
|
enum NOTIFY_VERSION_MINOR = 7;
|
||||||
|
enum NOTIFY_VERSION_MICRO = 5;
|
||||||
|
|
||||||
|
template NOTIFY_CHECK_VERSION(int major, int minor, int micro) {
|
||||||
|
enum NOTIFY_CHECK_VERSION = ((NOTIFY_VERSION_MAJOR > major) ||
|
||||||
|
(NOTIFY_VERSION_MAJOR == major && NOTIFY_VERSION_MINOR > minor) ||
|
||||||
|
(NOTIFY_VERSION_MAJOR == major && NOTIFY_VERSION_MINOR == minor &&
|
||||||
|
NOTIFY_VERSION_MICRO >= micro));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
alias ulong GType;
|
||||||
|
alias void function(void*) GFreeFunc;
|
||||||
|
|
||||||
|
struct GError {
|
||||||
|
uint domain;
|
||||||
|
int code;
|
||||||
|
char* message;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct GList {
|
||||||
|
void* data;
|
||||||
|
GList* next;
|
||||||
|
GList* prev;
|
||||||
|
}
|
||||||
|
|
||||||
|
// dummies
|
||||||
|
struct GdkPixbuf {}
|
||||||
|
struct GObject {}
|
||||||
|
struct GObjectClass {}
|
||||||
|
struct GVariant {}
|
||||||
|
|
||||||
|
GType notify_urgency_get_type();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* NOTIFY_EXPIRES_DEFAULT:
|
||||||
|
*
|
||||||
|
* The default expiration time on a notification.
|
||||||
|
*/
|
||||||
|
enum NOTIFY_EXPIRES_DEFAULT = -1;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* NOTIFY_EXPIRES_NEVER:
|
||||||
|
*
|
||||||
|
* The notification never expires. It stays open until closed by the calling API
|
||||||
|
* or the user.
|
||||||
|
*/
|
||||||
|
enum NOTIFY_EXPIRES_NEVER = 0;
|
||||||
|
|
||||||
|
// #define NOTIFY_TYPE_NOTIFICATION (notify_notification_get_type ())
|
||||||
|
// #define NOTIFY_NOTIFICATION(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), NOTIFY_TYPE_NOTIFICATION, NotifyNotification))
|
||||||
|
// #define NOTIFY_NOTIFICATION_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), NOTIFY_TYPE_NOTIFICATION, NotifyNotificationClass))
|
||||||
|
// #define NOTIFY_IS_NOTIFICATION(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), NOTIFY_TYPE_NOTIFICATION))
|
||||||
|
// #define NOTIFY_IS_NOTIFICATION_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), NOTIFY_TYPE_NOTIFICATION))
|
||||||
|
// #define NOTIFY_NOTIFICATION_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), NOTIFY_TYPE_NOTIFICATION, NotifyNotificationClass))
|
||||||
|
|
||||||
|
extern (C) {
|
||||||
|
struct NotifyNotificationPrivate;
|
||||||
|
|
||||||
|
struct NotifyNotification {
|
||||||
|
/*< private >*/
|
||||||
|
GObject parent_object;
|
||||||
|
|
||||||
|
NotifyNotificationPrivate *priv;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct NotifyNotificationClass {
|
||||||
|
GObjectClass parent_class;
|
||||||
|
|
||||||
|
/* Signals */
|
||||||
|
void function(NotifyNotification *notification) closed;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* NotifyUrgency:
|
||||||
|
* @NOTIFY_URGENCY_LOW: Low urgency. Used for unimportant notifications.
|
||||||
|
* @NOTIFY_URGENCY_NORMAL: Normal urgency. Used for most standard notifications.
|
||||||
|
* @NOTIFY_URGENCY_CRITICAL: Critical urgency. Used for very important notifications.
|
||||||
|
*
|
||||||
|
* The urgency level of the notification.
|
||||||
|
*/
|
||||||
|
enum NotifyUrgency {
|
||||||
|
NOTIFY_URGENCY_LOW,
|
||||||
|
NOTIFY_URGENCY_NORMAL,
|
||||||
|
NOTIFY_URGENCY_CRITICAL,
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* NotifyActionCallback:
|
||||||
|
* @notification:
|
||||||
|
* @action:
|
||||||
|
* @user_data:
|
||||||
|
*
|
||||||
|
* An action callback function.
|
||||||
|
*/
|
||||||
|
alias void function(NotifyNotification* notification, char* action, void* user_data) NotifyActionCallback;
|
||||||
|
|
||||||
|
|
||||||
|
GType notify_notification_get_type();
|
||||||
|
|
||||||
|
NotifyNotification* notify_notification_new(const(char)* summary, const(char)* body_, const(char)* icon);
|
||||||
|
|
||||||
|
bool notify_notification_update(NotifyNotification* notification, const(char)* summary, const(char)* body_, const(char)* icon);
|
||||||
|
|
||||||
|
bool notify_notification_show(NotifyNotification* notification, GError** error);
|
||||||
|
|
||||||
|
void notify_notification_set_timeout(NotifyNotification* notification, int timeout);
|
||||||
|
|
||||||
|
void notify_notification_set_category(NotifyNotification* notification, const(char)* category);
|
||||||
|
|
||||||
|
void notify_notification_set_urgency(NotifyNotification* notification, NotifyUrgency urgency);
|
||||||
|
|
||||||
|
void notify_notification_set_image_from_pixbuf(NotifyNotification* notification, GdkPixbuf* pixbuf);
|
||||||
|
|
||||||
|
void notify_notification_set_icon_from_pixbuf(NotifyNotification* notification, GdkPixbuf* icon);
|
||||||
|
|
||||||
|
void notify_notification_set_hint_int32(NotifyNotification* notification, const(char)* key, int value);
|
||||||
|
void notify_notification_set_hint_uint32(NotifyNotification* notification, const(char)* key, uint value);
|
||||||
|
|
||||||
|
void notify_notification_set_hint_double(NotifyNotification* notification, const(char)* key, double value);
|
||||||
|
|
||||||
|
void notify_notification_set_hint_string(NotifyNotification* notification, const(char)* key, const(char)* value);
|
||||||
|
|
||||||
|
void notify_notification_set_hint_byte(NotifyNotification* notification, const(char)* key, ubyte value);
|
||||||
|
|
||||||
|
void notify_notification_set_hint_byte_array(NotifyNotification* notification, const(char)* key, const(ubyte)* value, ulong len);
|
||||||
|
|
||||||
|
void notify_notification_set_hint(NotifyNotification* notification, const(char)* key, GVariant* value);
|
||||||
|
|
||||||
|
void notify_notification_set_app_name(NotifyNotification* notification, const(char)* app_name);
|
||||||
|
|
||||||
|
void notify_notification_clear_hints(NotifyNotification* notification);
|
||||||
|
|
||||||
|
void notify_notification_add_action(NotifyNotification* notification, const(char)* action, const(char)* label,
|
||||||
|
NotifyActionCallback callback, void* user_data, GFreeFunc free_func);
|
||||||
|
|
||||||
|
void notify_notification_clear_actions(NotifyNotification* notification);
|
||||||
|
bool notify_notification_close(NotifyNotification* notification, GError** error);
|
||||||
|
|
||||||
|
int notify_notification_get_closed_reason(const NotifyNotification* notification);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
bool notify_init(const(char)* app_name);
|
||||||
|
void notify_uninit();
|
||||||
|
bool notify_is_initted();
|
||||||
|
|
||||||
|
const(char)* notify_get_app_name();
|
||||||
|
void notify_set_app_name(const(char)* app_name);
|
||||||
|
|
||||||
|
GList *notify_get_server_caps();
|
||||||
|
|
||||||
|
bool notify_get_server_info(char** ret_name, char** ret_vendor, char** ret_version, char** ret_spec_version);
|
||||||
|
}
|
||||||
|
|
||||||
|
version(MainTest) {
|
||||||
|
import std.string;
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
|
||||||
|
notify_init("test".toStringz());
|
||||||
|
|
||||||
|
auto n = notify_notification_new("summary".toStringz(), "body".toStringz(), "none".toStringz());
|
||||||
|
GError* ge;
|
||||||
|
notify_notification_show(n, &ge);
|
||||||
|
|
||||||
|
scope(success) notify_uninit();
|
||||||
|
}
|
||||||
|
}
|
|
@ -545,7 +545,8 @@ final class OneDriveApi
|
||||||
http.perform();
|
http.perform();
|
||||||
} catch (CurlException e) {
|
} catch (CurlException e) {
|
||||||
// Potentially Timeout was reached on handle error
|
// Potentially Timeout was reached on handle error
|
||||||
log.error("\nAccess to the Microsoft OneDrive service timed out - Internet connectivity issue?\n");
|
// we issue warning/error in the catch routines so no need to warn here
|
||||||
|
// log.error("\nAccess to the Microsoft OneDrive service timed out - Internet connectivity issue?\n");
|
||||||
throw e;
|
throw e;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue