1
0
mirror of https://github.com/chylex/Nextcloud-Desktop.git synced 2026-04-03 09:11:33 +02:00

Compare commits

...

107 Commits

Author SHA1 Message Date
allexzander
3842d306f9 Merge pull request #2939 from nextcloud/bump_to_3.1.3
Bump release to 3.1.3
2021-02-18 12:33:45 +02:00
allexzander
bd675e0b35 Bump release to 3.1.3
Signed-off-by: allexzander <blackslayer4@gmail.com>
2021-02-18 12:25:39 +02:00
Nextcloud bot
2ec4220200 [tx-robot] updated from transifex 2021-02-18 03:51:55 +00:00
Nextcloud bot
c54c2069c7 [tx-robot] updated from transifex 2021-02-17 03:45:40 +00:00
Nextcloud bot
dbf8528bbd [tx-robot] updated from transifex 2021-02-16 03:47:08 +00:00
Nextcloud bot
5bd80e8212 [tx-robot] updated from transifex 2021-02-15 03:42:58 +00:00
Nextcloud bot
59efcf17a1 [tx-robot] updated from transifex 2021-02-14 03:40:51 +00:00
Nextcloud bot
1d939529e7 [tx-robot] updated from transifex 2021-02-13 03:43:13 +00:00
Kevin Ottens
b1ddd0e491 Merge pull request #2926 from nextcloud/backport/2919/stable-3.1
[stable-3.1] Validate the providers ssl certificate
2021-02-12 11:05:19 +01:00
Felix Weilbach
142180c0e2 Validate the providers ssl certificate
Signed-off-by: Felix Weilbach <felix.weilbach@nextcloud.com>
2021-02-12 09:51:29 +00:00
Nextcloud bot
c68975a90f [tx-robot] updated from transifex 2021-02-12 03:43:48 +00:00
Nextcloud bot
baed317b35 [tx-robot] updated from transifex 2021-02-11 03:43:26 +00:00
allexzander
cba745baca Merge pull request #2920 from nextcloud/backport/2906/stable-3.1
[stable-3.1] Validate sensitive URLs to onle allow http(s) schemes.
2021-02-10 14:22:02 +02:00
allexzander
856819a8ac Validate sensitive URLs to onle allow http(s) schemes.
Signed-off-by: allexzander <blackslayer4@gmail.com>
2021-02-10 11:47:56 +01:00
allexzander
c95436d3c4 Default parameter nullptr widget for openBrowser.
Signed-off-by: allexzander <blackslayer4@gmail.com>
2021-02-10 11:21:41 +01:00
Nextcloud bot
5173ac5225 [tx-robot] updated from transifex 2021-02-10 03:50:24 +00:00
Nextcloud bot
f8766d16d3 [tx-robot] updated from transifex 2021-02-09 03:43:34 +00:00
Nextcloud bot
e13fe74c64 [tx-robot] updated from transifex 2021-02-08 03:43:41 +00:00
Nextcloud bot
db4fa094d3 [tx-robot] updated from transifex 2021-02-07 03:44:35 +00:00
Nextcloud bot
0ac35a191e [tx-robot] updated from transifex 2021-02-06 03:47:16 +00:00
Nextcloud bot
951d9c9d18 [tx-robot] updated from transifex 2021-02-05 03:47:25 +00:00
Nextcloud bot
2d730f791a [tx-robot] updated from transifex 2021-02-04 03:42:40 +00:00
Nextcloud bot
96e8bae53d [tx-robot] updated from transifex 2021-02-03 03:57:54 +00:00
Nextcloud bot
81f20e26e3 [tx-robot] updated from transifex 2021-02-02 03:39:47 +00:00
Nextcloud bot
d5ac7f84de [tx-robot] updated from transifex 2021-02-01 03:45:58 +00:00
Nextcloud bot
1f3b198963 [tx-robot] updated from transifex 2021-01-31 03:42:50 +00:00
Nextcloud bot
f7322636bc [tx-robot] updated from transifex 2021-01-30 03:49:57 +00:00
Nextcloud bot
9a2485935b [tx-robot] updated from transifex 2021-01-29 03:48:41 +00:00
István Váradi
f537902933 Merge pull request #2884 from nextcloud/backport/2759/stable-3.1
[stable-3.1] Add support for Hirsute
2021-01-28 20:05:46 +01:00
István Váradi
4301fb48b1 Add support for Hirsute
Signed-off-by: István Váradi <ivaradi@varadiistvan.hu>
2021-01-28 18:52:13 +00:00
Kevin Ottens
9398260fb3 Merge pull request #2880 from nextcloud/bump_to_3.1.2
Bump release to 3.1.2
2021-01-28 09:27:09 +01:00
Kevin Ottens
ef3922a899 Bump release to 3.1.2
Signed-off-by: Kevin Ottens <kevin.ottens@nextcloud.com>
2021-01-28 08:07:49 +01:00
Nextcloud bot
6bb3db0546 [tx-robot] updated from transifex 2021-01-28 03:58:34 +00:00
Kevin Ottens
71633e78bb Merge pull request #2878 from nextcloud/backport/2872/stable-3.1
[stable-3.1] Use push notifications for Tray activities/notifications fetch trigger.
2021-01-27 19:34:36 +01:00
allexzander
1d3bc4e961 Use push notifications for Tray activities/notifications fetch trigger.
Signed-off-by: allexzander <blackslayer4@gmail.com>
2021-01-27 18:19:32 +00:00
Kevin Ottens
9f2190bad3 Merge pull request #2871 from nextcloud/backport/2867/stable-3.1
[stable-3.1] Start file conflict resolve dialog asynchronous
2021-01-27 09:22:35 +01:00
Felix Weilbach
aa6615ace6 Start file conflict resolve dialog asynchronous
Fixes #2804

Signed-off-by: Felix Weilbach <felix.weilbach@t-online.de>
2021-01-27 08:11:34 +00:00
Nextcloud bot
6599a93f78 [tx-robot] updated from transifex 2021-01-27 03:46:29 +00:00
Nextcloud bot
044a5ba2c2 [tx-robot] updated from transifex 2021-01-26 03:44:42 +00:00
Felix Weilbach
9eb5bd0192 Merge pull request #2866 from nextcloud/backport/2814/stable-3.1
[stable-3.1] Add push notifications for file changes
2021-01-25 09:48:29 -08:00
Felix Weilbach
38d7e1e98f Add push notifications for file changes
Resolves #2802

Signed-off-by: Felix Weilbach <felix.weilbach@nextcloud.com>
2021-01-25 18:25:55 +01:00
Nextcloud bot
6eea1322bf [tx-robot] updated from transifex 2021-01-25 03:43:14 +00:00
Nextcloud bot
51d9a9a8ae [tx-robot] updated from transifex 2021-01-24 03:41:07 +00:00
Nextcloud bot
ea14b99d04 [tx-robot] updated from transifex 2021-01-22 03:46:51 +00:00
Kevin Ottens
c94a535e9c Merge pull request #2849 from nextcloud/backport/2845/stable-3.1
[stable-3.1] Default to colored systray on linux
2021-01-21 08:13:37 +01:00
Kevin Ottens
167236b43d Fix the branding detection for monochrome icons on Mac
Signed-off-by: Kevin Ottens <kevin.ottens@nextcloud.com>
2021-01-21 07:02:47 +00:00
Kevin Ottens
c89b6b8094 Revert "Make monochrome icons the default on Linux and Mac OS."
This reverts commit 016410dbaa.

Signed-off-by: Kevin Ottens <kevin.ottens@nextcloud.com>
2021-01-21 07:02:47 +00:00
Nextcloud bot
a18cdf1d12 [tx-robot] updated from transifex 2021-01-21 03:45:52 +00:00
Kevin Ottens
540eed0526 Merge pull request #2846 from nextcloud/backport/2844/stable-3.1
[stable-3.1] Handle SVG branded clients
2021-01-20 16:16:33 +01:00
Kevin Ottens
00fc4807f7 Use APPLICATION_ICON_SET for themed icons
We now favor APPLICATION_ICON_SET to isBranded() regarding the decision
to use PNG or SVG for icons.

Signed-off-by: Kevin Ottens <kevin.ottens@nextcloud.com>
2021-01-20 15:08:49 +00:00
Kevin Ottens
0b43451008 Use the SVG wizard logo when APPLICATION_ICON_SET says so
Signed-off-by: Kevin Ottens <kevin.ottens@nextcloud.com>
2021-01-20 15:08:49 +00:00
Kevin Ottens
4b64603ee3 Add the APPLICATION_ICON_SET option
Also mention the svg possibly used in the wizard

Signed-off-by: Kevin Ottens <kevin.ottens@nextcloud.com>
2021-01-20 15:08:49 +00:00
Kevin Ottens
d5966eb385 Reference the wizard_logo.svg file from the resources
Somehow this was missing

Signed-off-by: Kevin Ottens <kevin.ottens@nextcloud.com>
2021-01-20 15:08:48 +00:00
Nextcloud bot
ece0557e43 [tx-robot] updated from transifex 2021-01-20 03:46:08 +00:00
Nextcloud bot
09be96e799 [tx-robot] updated from transifex 2021-01-19 03:44:21 +00:00
Nextcloud bot
39edbd3dd9 [tx-robot] updated from transifex 2021-01-18 03:43:20 +00:00
Nextcloud bot
a98e4fa394 [tx-robot] updated from transifex 2021-01-17 03:42:48 +00:00
Nextcloud bot
2ec4e77e8a [tx-robot] updated from transifex 2021-01-16 03:41:13 +00:00
Nextcloud bot
5b911bfec9 [tx-robot] updated from transifex 2021-01-15 03:48:37 +00:00
Nextcloud bot
e3f9ba1da3 [tx-robot] updated from transifex 2021-01-14 03:46:20 +00:00
Nextcloud bot
111627cd1f [tx-robot] updated from transifex 2021-01-13 03:51:05 +00:00
Nextcloud bot
2e37ab9861 [tx-robot] updated from transifex 2021-01-12 03:47:25 +00:00
Nextcloud bot
d14ab98746 [tx-robot] updated from transifex 2021-01-10 04:01:50 +00:00
Nextcloud bot
cd7dfe81f8 [tx-robot] updated from transifex 2021-01-09 03:57:53 +00:00
Nextcloud bot
f2a8fc46a6 [tx-robot] updated from transifex 2021-01-08 04:01:21 +00:00
Nextcloud bot
75d60213eb [tx-robot] updated from transifex 2021-01-07 03:56:58 +00:00
Nextcloud bot
44dfd9cfda [tx-robot] updated from transifex 2021-01-06 03:56:46 +00:00
Nextcloud bot
7bea176e6f [tx-robot] updated from transifex 2021-01-05 03:52:30 +00:00
Nextcloud bot
8938d5dd0e [tx-robot] updated from transifex 2021-01-04 03:53:57 +00:00
Nextcloud bot
42911da98a [tx-robot] updated from transifex 2021-01-03 03:54:23 +00:00
Nextcloud bot
1cb6145c5d [tx-robot] updated from transifex 2021-01-02 03:51:57 +00:00
Nextcloud bot
d8efb20881 [tx-robot] updated from transifex 2021-01-01 03:52:03 +00:00
Nextcloud bot
5abe4a2c51 [tx-robot] updated from transifex 2020-12-31 04:00:46 +00:00
Nextcloud bot
c7fd312f5c [tx-robot] updated from transifex 2020-12-30 03:47:56 +00:00
Nextcloud bot
dc4ea211da [tx-robot] updated from transifex 2020-12-29 03:47:56 +00:00
Nextcloud bot
be332aa4dd [tx-robot] updated from transifex 2020-12-28 03:45:12 +00:00
Nextcloud bot
db5bfdc4c8 [tx-robot] updated from transifex 2020-12-27 03:51:03 +00:00
Nextcloud bot
aa0632f375 [tx-robot] updated from transifex 2020-12-26 03:44:56 +00:00
Nextcloud bot
be38b10055 [tx-robot] updated from transifex 2020-12-25 03:44:25 +00:00
Nextcloud bot
da54720aec [tx-robot] updated from transifex 2020-12-24 03:45:48 +00:00
Nextcloud bot
83331e5336 [tx-robot] updated from transifex 2020-12-23 03:46:01 +00:00
Kevin Ottens
75c329f4ff Merge pull request #2761 from nextcloud/bump_to_3.1.1
Bump release to 3.1.1
2020-12-22 10:54:32 +01:00
Kevin Ottens
b69c047be1 Bump release to 3.1.1
Signed-off-by: Kevin Ottens <kevin.ottens@nextcloud.com>
2020-12-22 10:44:45 +01:00
Nextcloud bot
f0292b15a0 [tx-robot] updated from transifex 2020-12-22 03:47:02 +00:00
Kevin Ottens
e1b0e3474f Merge pull request #2753 from nextcloud/backport/2739/stable-3.1
[stable-3.1] Fixed the autostart for AppImages. See #2504.
2020-12-21 12:15:54 +01:00
Hannah Rittich
98077abfba Fixed the autostart for AppImages. See #2504.
Signed-off-by: Hannah Rittich <hrittich@users.noreply.github.com>
2020-12-21 11:08:29 +00:00
Nextcloud bot
1d265c791b [tx-robot] updated from transifex 2020-12-21 03:44:58 +00:00
Nextcloud bot
f93829afd7 [tx-robot] updated from transifex 2020-12-20 03:47:21 +00:00
Nextcloud bot
68bc4367d2 [tx-robot] updated from transifex 2020-12-19 03:45:53 +00:00
Nextcloud bot
1ead3608f0 [tx-robot] updated from transifex 2020-12-18 03:47:04 +00:00
Kevin Ottens
48dcd9c8f0 Merge pull request #2730 from nextcloud/backport/2725/stable-3.1
[stable-3.1] Make monochrome icons the default on Linux and Mac OS.
2020-12-17 11:00:24 +01:00
Camila
7688d5f607 Make monochrome icons the default on Linux and Mac OS.
Unless it is branded with other icons.

Signed-off-by: Camila <hello@camila.codes>
2020-12-17 07:03:54 +00:00
Nextcloud bot
7957b1b6b7 [tx-robot] updated from transifex 2020-12-17 03:45:10 +00:00
Nextcloud bot
f3957ba72b [tx-robot] updated from transifex 2020-12-16 03:47:14 +00:00
Camila
b391d88ed4 Merge pull request #2717 from nextcloud/backport/2714/stable-3.1
[stable-3.1] Ensure a sync happens after a conflict resolution
2020-12-15 11:18:31 +01:00
Kevin Ottens
9774b6a429 Ensure a sync happens after a conflict resolution
You'd expect that after a conflict resolution the file watcher would
pick up the change and trigger a sync. For some reason it doesn't seem
to happen on at least some Ubuntu systems. In such cases the user would
then still have a stale conflict entry in the activity list and wouldn't
be able to do anything with it.

Signed-off-by: Kevin Ottens <kevin.ottens@nextcloud.com>
2020-12-15 10:04:15 +00:00
Camila
2e216c8f29 Merge pull request #2715 from nextcloud/backport/2713/stable-3.1
[stable-3.1] UserModel: check indices are inside the user list
2020-12-15 11:03:12 +01:00
Kevin Ottens
8997d5ced9 UserModel: check indices are inside the user list
The model was just checking for the user list being empty or not which
is overly optimistic. Indeed there might be cases where the id is
actually outside the boundaries so properly check for this.

Signed-off-by: Kevin Ottens <kevin.ottens@nextcloud.com>
2020-12-15 09:51:38 +00:00
Camila
c85d12425d Merge pull request #2716 from nextcloud/backport/2698/stable-3.1
[stable-3.1] Use the icon color property to color the icons in the tray window header.
2020-12-15 10:50:34 +01:00
Camila
3fa796e11e Use the icon color property to color the icons in the tray window header.
The icon color is set with APPLICATION_WIZARD_HEADER_TITLE_COLOR in the
theme.

Signed-off-by: Camila <hello@camila.codes>
2020-12-15 09:44:51 +00:00
Nextcloud bot
583c4960d8 [tx-robot] updated from transifex 2020-12-15 03:47:30 +00:00
Kevin Ottens
6a94f0deef Merge pull request #2709 from nextcloud/backport/2708/stable-3.1
[stable-3.1] Have the new account wizard open again
2020-12-14 16:38:24 +01:00
Kevin Ottens
3c9e065170 Have the new account wizard open again
UserModel can't be connected to AccountSettings if the settings dialog
doesn't exist. This is the case now since we delay the creation of that
dialog and free it after use.

Instead it should be properly channeled through the Systray object all
the way up to OwncloudGui which knows how to handle this properly.

Signed-off-by: Kevin Ottens <kevin.ottens@nextcloud.com>
2020-12-14 15:29:24 +00:00
Nextcloud bot
a0719b782b [tx-robot] updated from transifex 2020-12-14 03:47:59 +00:00
Nextcloud bot
6caff18d7c [tx-robot] updated from transifex 2020-12-13 03:43:55 +00:00
Nextcloud bot
9114419d8e [tx-robot] updated from transifex 2020-12-12 03:46:15 +00:00
Nextcloud bot
3991350c47 [tx-robot] updated from transifex 2020-12-11 03:44:45 +00:00
156 changed files with 71781 additions and 41087 deletions

View File

@@ -8,193 +8,16 @@ GenericName=Folder Sync
Icon=@APPLICATION_ICON_NAME@
Keywords=@APPLICATION_NAME@;syncing;file;sharing;
X-GNOME-Autostart-Delay=3
# Translations
MimeType=application/vnd.@APPLICATION_EXECUTABLE@;
Actions=Quit;
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
[Desktop Action Quit]
Exec=@APPLICATION_EXECUTABLE@ --quit
Name=Quit @APPLICATION_NAME@
Icon=@APPLICATION_EXECUTABLE@
# Translations

View File

@@ -8,193 +8,16 @@ GenericName=Folder Sync
Icon=@APPLICATION_ICON_NAME@
Keywords=@APPLICATION_NAME@;syncing;file;sharing;
X-GNOME-Autostart-Delay=3
# Translations
MimeType=application/vnd.@APPLICATION_EXECUTABLE@;
Actions=Quit;
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
[Desktop Action Quit]
Exec=@APPLICATION_EXECUTABLE@ --quit
Name=Quit @APPLICATION_NAME@
Icon=@APPLICATION_EXECUTABLE@
# Translations

View File

@@ -8,193 +8,16 @@ GenericName=Folder Sync
Icon=@APPLICATION_ICON_NAME@
Keywords=@APPLICATION_NAME@;syncing;file;sharing;
X-GNOME-Autostart-Delay=3
# Translations
MimeType=application/vnd.@APPLICATION_EXECUTABLE@;
Actions=Quit;
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
[Desktop Action Quit]
Exec=@APPLICATION_EXECUTABLE@ --quit
Name=Quit @APPLICATION_NAME@
Icon=@APPLICATION_EXECUTABLE@
# Translations

View File

@@ -8,193 +8,16 @@ GenericName=Folder Sync
Icon=@APPLICATION_ICON_NAME@
Keywords=@APPLICATION_NAME@;syncing;file;sharing;
X-GNOME-Autostart-Delay=3
# Translations
MimeType=application/vnd.@APPLICATION_EXECUTABLE@;
Actions=Quit;
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
[Desktop Action Quit]
Exec=@APPLICATION_EXECUTABLE@ --quit
Name=Quit @APPLICATION_NAME@
Icon=@APPLICATION_EXECUTABLE@
# Translations

View File

@@ -8,193 +8,16 @@ GenericName=Folder Sync
Icon=@APPLICATION_ICON_NAME@
Keywords=@APPLICATION_NAME@;syncing;file;sharing;
X-GNOME-Autostart-Delay=3
# Translations
MimeType=application/vnd.@APPLICATION_EXECUTABLE@;
Actions=Quit;
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
[Desktop Action Quit]
Exec=@APPLICATION_EXECUTABLE@ --quit
Name=Quit @APPLICATION_NAME@
Icon=@APPLICATION_EXECUTABLE@
# Translations

View File

@@ -8,193 +8,16 @@ GenericName=Folder Sync
Icon=@APPLICATION_ICON_NAME@
Keywords=@APPLICATION_NAME@;syncing;file;sharing;
X-GNOME-Autostart-Delay=3
# Translations
MimeType=application/vnd.@APPLICATION_EXECUTABLE@;
Actions=Quit;
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
[Desktop Action Quit]
Exec=@APPLICATION_EXECUTABLE@ --quit
Name=Quit @APPLICATION_NAME@
Icon=@APPLICATION_EXECUTABLE@
# Translations

View File

@@ -8,193 +8,16 @@ GenericName=Folder Sync
Icon=@APPLICATION_ICON_NAME@
Keywords=@APPLICATION_NAME@;syncing;file;sharing;
X-GNOME-Autostart-Delay=3
# Translations
MimeType=application/vnd.@APPLICATION_EXECUTABLE@;
Actions=Quit;
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
[Desktop Action Quit]
Exec=@APPLICATION_EXECUTABLE@ --quit
Name=Quit @APPLICATION_NAME@
Icon=@APPLICATION_EXECUTABLE@
# Translations

View File

@@ -8,197 +8,20 @@ GenericName=Folder Sync
Icon=@APPLICATION_ICON_NAME@
Keywords=@APPLICATION_NAME@;syncing;file;sharing;
X-GNOME-Autostart-Delay=3
# Translations
MimeType=application/vnd.@APPLICATION_EXECUTABLE@;
Actions=Quit;
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
[Desktop Action Quit]
Exec=@APPLICATION_EXECUTABLE@ --quit
Name=Quit @APPLICATION_NAME@
Icon=@APPLICATION_EXECUTABLE@
# Translations
Icon[de]=@APPLICATION_ICON_NAME@
Name[de]=@APPLICATION_NAME@ Client zur Desktop-Synchronisierung
Comment[de]=@APPLICATION_NAME@ Client zur Desktop-Synchronisierung
GenericName[de]=Synchronisierungsordner
GenericName[de]=Ordner-Synchronisation

View File

@@ -8,193 +8,16 @@ GenericName=Folder Sync
Icon=@APPLICATION_ICON_NAME@
Keywords=@APPLICATION_NAME@;syncing;file;sharing;
X-GNOME-Autostart-Delay=3
# Translations
MimeType=application/vnd.@APPLICATION_EXECUTABLE@;
Actions=Quit;
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
[Desktop Action Quit]
Exec=@APPLICATION_EXECUTABLE@ --quit
Name=Quit @APPLICATION_NAME@
Icon=@APPLICATION_EXECUTABLE@
# Translations

View File

@@ -8,193 +8,16 @@ GenericName=Folder Sync
Icon=@APPLICATION_ICON_NAME@
Keywords=@APPLICATION_NAME@;syncing;file;sharing;
X-GNOME-Autostart-Delay=3
# Translations
MimeType=application/vnd.@APPLICATION_EXECUTABLE@;
Actions=Quit;
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
[Desktop Action Quit]
Exec=@APPLICATION_EXECUTABLE@ --quit
Name=Quit @APPLICATION_NAME@
Icon=@APPLICATION_EXECUTABLE@
# Translations

View File

@@ -8,193 +8,16 @@ GenericName=Folder Sync
Icon=@APPLICATION_ICON_NAME@
Keywords=@APPLICATION_NAME@;syncing;file;sharing;
X-GNOME-Autostart-Delay=3
# Translations
MimeType=application/vnd.@APPLICATION_EXECUTABLE@;
Actions=Quit;
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
[Desktop Action Quit]
Exec=@APPLICATION_EXECUTABLE@ --quit
Name=Quit @APPLICATION_NAME@
Icon=@APPLICATION_EXECUTABLE@
# Translations

View File

@@ -8,193 +8,16 @@ GenericName=Folder Sync
Icon=@APPLICATION_ICON_NAME@
Keywords=@APPLICATION_NAME@;syncing;file;sharing;
X-GNOME-Autostart-Delay=3
# Translations
MimeType=application/vnd.@APPLICATION_EXECUTABLE@;
Actions=Quit;
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
[Desktop Action Quit]
Exec=@APPLICATION_EXECUTABLE@ --quit
Name=Quit @APPLICATION_NAME@
Icon=@APPLICATION_EXECUTABLE@
# Translations

View File

@@ -8,193 +8,16 @@ GenericName=Folder Sync
Icon=@APPLICATION_ICON_NAME@
Keywords=@APPLICATION_NAME@;syncing;file;sharing;
X-GNOME-Autostart-Delay=3
# Translations
MimeType=application/vnd.@APPLICATION_EXECUTABLE@;
Actions=Quit;
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
[Desktop Action Quit]
Exec=@APPLICATION_EXECUTABLE@ --quit
Name=Quit @APPLICATION_NAME@
Icon=@APPLICATION_EXECUTABLE@
# Translations

View File

@@ -8,193 +8,16 @@ GenericName=Folder Sync
Icon=@APPLICATION_ICON_NAME@
Keywords=@APPLICATION_NAME@;syncing;file;sharing;
X-GNOME-Autostart-Delay=3
# Translations
MimeType=application/vnd.@APPLICATION_EXECUTABLE@;
Actions=Quit;
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
[Desktop Action Quit]
Exec=@APPLICATION_EXECUTABLE@ --quit
Name=Quit @APPLICATION_NAME@
Icon=@APPLICATION_EXECUTABLE@
# Translations

View File

@@ -8,193 +8,16 @@ GenericName=Folder Sync
Icon=@APPLICATION_ICON_NAME@
Keywords=@APPLICATION_NAME@;syncing;file;sharing;
X-GNOME-Autostart-Delay=3
# Translations
MimeType=application/vnd.@APPLICATION_EXECUTABLE@;
Actions=Quit;
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
[Desktop Action Quit]
Exec=@APPLICATION_EXECUTABLE@ --quit
Name=Quit @APPLICATION_NAME@
Icon=@APPLICATION_EXECUTABLE@
# Translations

View File

@@ -8,196 +8,20 @@ GenericName=Folder Sync
Icon=@APPLICATION_ICON_NAME@
Keywords=@APPLICATION_NAME@;syncing;file;sharing;
X-GNOME-Autostart-Delay=3
# Translations
MimeType=application/vnd.@APPLICATION_EXECUTABLE@;
Actions=Quit;
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
[Desktop Action Quit]
Exec=@APPLICATION_EXECUTABLE@ --quit
Name=Quit @APPLICATION_NAME@
Icon=@APPLICATION_EXECUTABLE@
# Translations
Icon[es_DO]=@APPLICATION_ICON_NAME@
Name[es_DO]=@APPLICATION_NAME@ Cliente de sincronización de escritorio
Comment[es_DO]=@APPLICATION_NAME@ Cliente de sincronización de escritorio
GenericName[es_DO]=Sincronización de carpeta

View File

@@ -8,193 +8,16 @@ GenericName=Folder Sync
Icon=@APPLICATION_ICON_NAME@
Keywords=@APPLICATION_NAME@;syncing;file;sharing;
X-GNOME-Autostart-Delay=3
# Translations
MimeType=application/vnd.@APPLICATION_EXECUTABLE@;
Actions=Quit;
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
[Desktop Action Quit]
Exec=@APPLICATION_EXECUTABLE@ --quit
Name=Quit @APPLICATION_NAME@
Icon=@APPLICATION_EXECUTABLE@
# Translations

View File

@@ -8,193 +8,16 @@ GenericName=Folder Sync
Icon=@APPLICATION_ICON_NAME@
Keywords=@APPLICATION_NAME@;syncing;file;sharing;
X-GNOME-Autostart-Delay=3
# Translations
MimeType=application/vnd.@APPLICATION_EXECUTABLE@;
Actions=Quit;
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
[Desktop Action Quit]
Exec=@APPLICATION_EXECUTABLE@ --quit
Name=Quit @APPLICATION_NAME@
Icon=@APPLICATION_EXECUTABLE@
# Translations

View File

@@ -8,193 +8,16 @@ GenericName=Folder Sync
Icon=@APPLICATION_ICON_NAME@
Keywords=@APPLICATION_NAME@;syncing;file;sharing;
X-GNOME-Autostart-Delay=3
# Translations
MimeType=application/vnd.@APPLICATION_EXECUTABLE@;
Actions=Quit;
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
[Desktop Action Quit]
Exec=@APPLICATION_EXECUTABLE@ --quit
Name=Quit @APPLICATION_NAME@
Icon=@APPLICATION_EXECUTABLE@
# Translations

View File

@@ -8,193 +8,16 @@ GenericName=Folder Sync
Icon=@APPLICATION_ICON_NAME@
Keywords=@APPLICATION_NAME@;syncing;file;sharing;
X-GNOME-Autostart-Delay=3
# Translations
MimeType=application/vnd.@APPLICATION_EXECUTABLE@;
Actions=Quit;
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
[Desktop Action Quit]
Exec=@APPLICATION_EXECUTABLE@ --quit
Name=Quit @APPLICATION_NAME@
Icon=@APPLICATION_EXECUTABLE@
# Translations

View File

@@ -8,193 +8,16 @@ GenericName=Folder Sync
Icon=@APPLICATION_ICON_NAME@
Keywords=@APPLICATION_NAME@;syncing;file;sharing;
X-GNOME-Autostart-Delay=3
# Translations
MimeType=application/vnd.@APPLICATION_EXECUTABLE@;
Actions=Quit;
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
[Desktop Action Quit]
Exec=@APPLICATION_EXECUTABLE@ --quit
Name=Quit @APPLICATION_NAME@
Icon=@APPLICATION_EXECUTABLE@
# Translations

View File

@@ -8,193 +8,16 @@ GenericName=Folder Sync
Icon=@APPLICATION_ICON_NAME@
Keywords=@APPLICATION_NAME@;syncing;file;sharing;
X-GNOME-Autostart-Delay=3
# Translations
MimeType=application/vnd.@APPLICATION_EXECUTABLE@;
Actions=Quit;
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
[Desktop Action Quit]
Exec=@APPLICATION_EXECUTABLE@ --quit
Name=Quit @APPLICATION_NAME@
Icon=@APPLICATION_EXECUTABLE@
# Translations

View File

@@ -8,193 +8,16 @@ GenericName=Folder Sync
Icon=@APPLICATION_ICON_NAME@
Keywords=@APPLICATION_NAME@;syncing;file;sharing;
X-GNOME-Autostart-Delay=3
# Translations
MimeType=application/vnd.@APPLICATION_EXECUTABLE@;
Actions=Quit;
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
[Desktop Action Quit]
Exec=@APPLICATION_EXECUTABLE@ --quit
Name=Quit @APPLICATION_NAME@
Icon=@APPLICATION_EXECUTABLE@
# Translations

View File

@@ -8,193 +8,16 @@ GenericName=Folder Sync
Icon=@APPLICATION_ICON_NAME@
Keywords=@APPLICATION_NAME@;syncing;file;sharing;
X-GNOME-Autostart-Delay=3
# Translations
MimeType=application/vnd.@APPLICATION_EXECUTABLE@;
Actions=Quit;
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
[Desktop Action Quit]
Exec=@APPLICATION_EXECUTABLE@ --quit
Name=Quit @APPLICATION_NAME@
Icon=@APPLICATION_EXECUTABLE@
# Translations

View File

@@ -8,193 +8,16 @@ GenericName=Folder Sync
Icon=@APPLICATION_ICON_NAME@
Keywords=@APPLICATION_NAME@;syncing;file;sharing;
X-GNOME-Autostart-Delay=3
# Translations
MimeType=application/vnd.@APPLICATION_EXECUTABLE@;
Actions=Quit;
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
[Desktop Action Quit]
Exec=@APPLICATION_EXECUTABLE@ --quit
Name=Quit @APPLICATION_NAME@
Icon=@APPLICATION_EXECUTABLE@
# Translations

View File

@@ -8,193 +8,16 @@ GenericName=Folder Sync
Icon=@APPLICATION_ICON_NAME@
Keywords=@APPLICATION_NAME@;syncing;file;sharing;
X-GNOME-Autostart-Delay=3
# Translations
MimeType=application/vnd.@APPLICATION_EXECUTABLE@;
Actions=Quit;
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
[Desktop Action Quit]
Exec=@APPLICATION_EXECUTABLE@ --quit
Name=Quit @APPLICATION_NAME@
Icon=@APPLICATION_EXECUTABLE@
# Translations

View File

@@ -8,193 +8,16 @@ GenericName=Folder Sync
Icon=@APPLICATION_ICON_NAME@
Keywords=@APPLICATION_NAME@;syncing;file;sharing;
X-GNOME-Autostart-Delay=3
# Translations
MimeType=application/vnd.@APPLICATION_EXECUTABLE@;
Actions=Quit;
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
[Desktop Action Quit]
Exec=@APPLICATION_EXECUTABLE@ --quit
Name=Quit @APPLICATION_NAME@
Icon=@APPLICATION_EXECUTABLE@
# Translations

View File

@@ -8,193 +8,16 @@ GenericName=Folder Sync
Icon=@APPLICATION_ICON_NAME@
Keywords=@APPLICATION_NAME@;syncing;file;sharing;
X-GNOME-Autostart-Delay=3
# Translations
MimeType=application/vnd.@APPLICATION_EXECUTABLE@;
Actions=Quit;
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
[Desktop Action Quit]
Exec=@APPLICATION_EXECUTABLE@ --quit
Name=Quit @APPLICATION_NAME@
Icon=@APPLICATION_EXECUTABLE@
# Translations

View File

@@ -8,193 +8,16 @@ GenericName=Folder Sync
Icon=@APPLICATION_ICON_NAME@
Keywords=@APPLICATION_NAME@;syncing;file;sharing;
X-GNOME-Autostart-Delay=3
# Translations
MimeType=application/vnd.@APPLICATION_EXECUTABLE@;
Actions=Quit;
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
[Desktop Action Quit]
Exec=@APPLICATION_EXECUTABLE@ --quit
Name=Quit @APPLICATION_NAME@
Icon=@APPLICATION_EXECUTABLE@
# Translations

View File

@@ -8,193 +8,16 @@ GenericName=Folder Sync
Icon=@APPLICATION_ICON_NAME@
Keywords=@APPLICATION_NAME@;syncing;file;sharing;
X-GNOME-Autostart-Delay=3
# Translations
MimeType=application/vnd.@APPLICATION_EXECUTABLE@;
Actions=Quit;
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
[Desktop Action Quit]
Exec=@APPLICATION_EXECUTABLE@ --quit
Name=Quit @APPLICATION_NAME@
Icon=@APPLICATION_EXECUTABLE@
# Translations

View File

@@ -8,193 +8,16 @@ GenericName=Folder Sync
Icon=@APPLICATION_ICON_NAME@
Keywords=@APPLICATION_NAME@;syncing;file;sharing;
X-GNOME-Autostart-Delay=3
# Translations
MimeType=application/vnd.@APPLICATION_EXECUTABLE@;
Actions=Quit;
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
[Desktop Action Quit]
Exec=@APPLICATION_EXECUTABLE@ --quit
Name=Quit @APPLICATION_NAME@
Icon=@APPLICATION_EXECUTABLE@
# Translations

View File

@@ -8,193 +8,16 @@ GenericName=Folder Sync
Icon=@APPLICATION_ICON_NAME@
Keywords=@APPLICATION_NAME@;syncing;file;sharing;
X-GNOME-Autostart-Delay=3
# Translations
MimeType=application/vnd.@APPLICATION_EXECUTABLE@;
Actions=Quit;
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
[Desktop Action Quit]
Exec=@APPLICATION_EXECUTABLE@ --quit
Name=Quit @APPLICATION_NAME@
Icon=@APPLICATION_EXECUTABLE@
# Translations

View File

@@ -8,193 +8,16 @@ GenericName=Folder Sync
Icon=@APPLICATION_ICON_NAME@
Keywords=@APPLICATION_NAME@;syncing;file;sharing;
X-GNOME-Autostart-Delay=3
# Translations
MimeType=application/vnd.@APPLICATION_EXECUTABLE@;
Actions=Quit;
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
[Desktop Action Quit]
Exec=@APPLICATION_EXECUTABLE@ --quit
Name=Quit @APPLICATION_NAME@
Icon=@APPLICATION_EXECUTABLE@
# Translations

View File

@@ -8,193 +8,16 @@ GenericName=Folder Sync
Icon=@APPLICATION_ICON_NAME@
Keywords=@APPLICATION_NAME@;syncing;file;sharing;
X-GNOME-Autostart-Delay=3
# Translations
MimeType=application/vnd.@APPLICATION_EXECUTABLE@;
Actions=Quit;
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
[Desktop Action Quit]
Exec=@APPLICATION_EXECUTABLE@ --quit
Name=Quit @APPLICATION_NAME@
Icon=@APPLICATION_EXECUTABLE@
# Translations

View File

@@ -8,193 +8,16 @@ GenericName=Folder Sync
Icon=@APPLICATION_ICON_NAME@
Keywords=@APPLICATION_NAME@;syncing;file;sharing;
X-GNOME-Autostart-Delay=3
# Translations
MimeType=application/vnd.@APPLICATION_EXECUTABLE@;
Actions=Quit;
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
[Desktop Action Quit]
Exec=@APPLICATION_EXECUTABLE@ --quit
Name=Quit @APPLICATION_NAME@
Icon=@APPLICATION_EXECUTABLE@
# Translations

View File

@@ -8,193 +8,16 @@ GenericName=Folder Sync
Icon=@APPLICATION_ICON_NAME@
Keywords=@APPLICATION_NAME@;syncing;file;sharing;
X-GNOME-Autostart-Delay=3
# Translations
MimeType=application/vnd.@APPLICATION_EXECUTABLE@;
Actions=Quit;
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
[Desktop Action Quit]
Exec=@APPLICATION_EXECUTABLE@ --quit
Name=Quit @APPLICATION_NAME@
Icon=@APPLICATION_EXECUTABLE@
# Translations

View File

@@ -8,193 +8,16 @@ GenericName=Folder Sync
Icon=@APPLICATION_ICON_NAME@
Keywords=@APPLICATION_NAME@;syncing;file;sharing;
X-GNOME-Autostart-Delay=3
# Translations
MimeType=application/vnd.@APPLICATION_EXECUTABLE@;
Actions=Quit;
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
[Desktop Action Quit]
Exec=@APPLICATION_EXECUTABLE@ --quit
Name=Quit @APPLICATION_NAME@
Icon=@APPLICATION_EXECUTABLE@
# Translations

View File

@@ -8,193 +8,16 @@ GenericName=Folder Sync
Icon=@APPLICATION_ICON_NAME@
Keywords=@APPLICATION_NAME@;syncing;file;sharing;
X-GNOME-Autostart-Delay=3
# Translations
MimeType=application/vnd.@APPLICATION_EXECUTABLE@;
Actions=Quit;
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
[Desktop Action Quit]
Exec=@APPLICATION_EXECUTABLE@ --quit
Name=Quit @APPLICATION_NAME@
Icon=@APPLICATION_EXECUTABLE@
# Translations

View File

@@ -8,193 +8,16 @@ GenericName=Folder Sync
Icon=@APPLICATION_ICON_NAME@
Keywords=@APPLICATION_NAME@;syncing;file;sharing;
X-GNOME-Autostart-Delay=3
# Translations
MimeType=application/vnd.@APPLICATION_EXECUTABLE@;
Actions=Quit;
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
[Desktop Action Quit]
Exec=@APPLICATION_EXECUTABLE@ --quit
Name=Quit @APPLICATION_NAME@
Icon=@APPLICATION_EXECUTABLE@
# Translations

View File

@@ -8,193 +8,16 @@ GenericName=Folder Sync
Icon=@APPLICATION_ICON_NAME@
Keywords=@APPLICATION_NAME@;syncing;file;sharing;
X-GNOME-Autostart-Delay=3
# Translations
MimeType=application/vnd.@APPLICATION_EXECUTABLE@;
Actions=Quit;
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
[Desktop Action Quit]
Exec=@APPLICATION_EXECUTABLE@ --quit
Name=Quit @APPLICATION_NAME@
Icon=@APPLICATION_EXECUTABLE@
# Translations

View File

@@ -8,193 +8,16 @@ GenericName=Folder Sync
Icon=@APPLICATION_ICON_NAME@
Keywords=@APPLICATION_NAME@;syncing;file;sharing;
X-GNOME-Autostart-Delay=3
# Translations
MimeType=application/vnd.@APPLICATION_EXECUTABLE@;
Actions=Quit;
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
[Desktop Action Quit]
Exec=@APPLICATION_EXECUTABLE@ --quit
Name=Quit @APPLICATION_NAME@
Icon=@APPLICATION_EXECUTABLE@
# Translations

View File

@@ -8,193 +8,16 @@ GenericName=Folder Sync
Icon=@APPLICATION_ICON_NAME@
Keywords=@APPLICATION_NAME@;syncing;file;sharing;
X-GNOME-Autostart-Delay=3
# Translations
MimeType=application/vnd.@APPLICATION_EXECUTABLE@;
Actions=Quit;
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
[Desktop Action Quit]
Exec=@APPLICATION_EXECUTABLE@ --quit
Name=Quit @APPLICATION_NAME@
Icon=@APPLICATION_EXECUTABLE@
# Translations

View File

@@ -8,193 +8,16 @@ GenericName=Folder Sync
Icon=@APPLICATION_ICON_NAME@
Keywords=@APPLICATION_NAME@;syncing;file;sharing;
X-GNOME-Autostart-Delay=3
# Translations
MimeType=application/vnd.@APPLICATION_EXECUTABLE@;
Actions=Quit;
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
[Desktop Action Quit]
Exec=@APPLICATION_EXECUTABLE@ --quit
Name=Quit @APPLICATION_NAME@
Icon=@APPLICATION_EXECUTABLE@
# Translations

View File

@@ -8,193 +8,16 @@ GenericName=Folder Sync
Icon=@APPLICATION_ICON_NAME@
Keywords=@APPLICATION_NAME@;syncing;file;sharing;
X-GNOME-Autostart-Delay=3
# Translations
MimeType=application/vnd.@APPLICATION_EXECUTABLE@;
Actions=Quit;
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
[Desktop Action Quit]
Exec=@APPLICATION_EXECUTABLE@ --quit
Name=Quit @APPLICATION_NAME@
Icon=@APPLICATION_EXECUTABLE@
# Translations

View File

@@ -8,193 +8,16 @@ GenericName=Folder Sync
Icon=@APPLICATION_ICON_NAME@
Keywords=@APPLICATION_NAME@;syncing;file;sharing;
X-GNOME-Autostart-Delay=3
# Translations
MimeType=application/vnd.@APPLICATION_EXECUTABLE@;
Actions=Quit;
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
[Desktop Action Quit]
Exec=@APPLICATION_EXECUTABLE@ --quit
Name=Quit @APPLICATION_NAME@
Icon=@APPLICATION_EXECUTABLE@
# Translations

View File

@@ -0,0 +1,27 @@
[Desktop Entry]
Categories=Utility;X-SuSE-SyncUtility;
Type=Application
Exec=@APPLICATION_EXECUTABLE@
Name=@APPLICATION_NAME@ desktop sync client
Comment=@APPLICATION_NAME@ desktop synchronization client
GenericName=Folder Sync
Icon=@APPLICATION_ICON_NAME@
Keywords=@APPLICATION_NAME@;syncing;file;sharing;
X-GNOME-Autostart-Delay=3
MimeType=application/vnd.@APPLICATION_EXECUTABLE@;
Actions=Quit;
# Translations
[Desktop Action Quit]
Exec=@APPLICATION_EXECUTABLE@ --quit
Name=Quit @APPLICATION_NAME@
Icon=@APPLICATION_EXECUTABLE@
# Translations
Icon[sc]=@NÙMENE_ICONA_APLICATZIONE@
Name[sc]=@NÙMENE_APLICATZIONE@ cliente sicronizadore de iscrivania
Comment[sc]=@NÙMENE_APLICATZIONE@ cliente de sincronizatzione iscrivania
GenericName[sc]=Sincronizadore de cartellas

View File

@@ -8,193 +8,16 @@ GenericName=Folder Sync
Icon=@APPLICATION_ICON_NAME@
Keywords=@APPLICATION_NAME@;syncing;file;sharing;
X-GNOME-Autostart-Delay=3
# Translations
MimeType=application/vnd.@APPLICATION_EXECUTABLE@;
Actions=Quit;
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
[Desktop Action Quit]
Exec=@APPLICATION_EXECUTABLE@ --quit
Name=Quit @APPLICATION_NAME@
Icon=@APPLICATION_EXECUTABLE@
# Translations

View File

@@ -8,193 +8,16 @@ GenericName=Folder Sync
Icon=@APPLICATION_ICON_NAME@
Keywords=@APPLICATION_NAME@;syncing;file;sharing;
X-GNOME-Autostart-Delay=3
# Translations
MimeType=application/vnd.@APPLICATION_EXECUTABLE@;
Actions=Quit;
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
[Desktop Action Quit]
Exec=@APPLICATION_EXECUTABLE@ --quit
Name=Quit @APPLICATION_NAME@
Icon=@APPLICATION_EXECUTABLE@
# Translations

View File

@@ -8,193 +8,16 @@ GenericName=Folder Sync
Icon=@APPLICATION_ICON_NAME@
Keywords=@APPLICATION_NAME@;syncing;file;sharing;
X-GNOME-Autostart-Delay=3
# Translations
MimeType=application/vnd.@APPLICATION_EXECUTABLE@;
Actions=Quit;
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
[Desktop Action Quit]
Exec=@APPLICATION_EXECUTABLE@ --quit
Name=Quit @APPLICATION_NAME@
Icon=@APPLICATION_EXECUTABLE@
# Translations

View File

@@ -8,193 +8,16 @@ GenericName=Folder Sync
Icon=@APPLICATION_ICON_NAME@
Keywords=@APPLICATION_NAME@;syncing;file;sharing;
X-GNOME-Autostart-Delay=3
# Translations
MimeType=application/vnd.@APPLICATION_EXECUTABLE@;
Actions=Quit;
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
[Desktop Action Quit]
Exec=@APPLICATION_EXECUTABLE@ --quit
Name=Quit @APPLICATION_NAME@
Icon=@APPLICATION_EXECUTABLE@
# Translations

View File

@@ -8,193 +8,16 @@ GenericName=Folder Sync
Icon=@APPLICATION_ICON_NAME@
Keywords=@APPLICATION_NAME@;syncing;file;sharing;
X-GNOME-Autostart-Delay=3
# Translations
MimeType=application/vnd.@APPLICATION_EXECUTABLE@;
Actions=Quit;
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
[Desktop Action Quit]
Exec=@APPLICATION_EXECUTABLE@ --quit
Name=Quit @APPLICATION_NAME@
Icon=@APPLICATION_EXECUTABLE@
# Translations

View File

@@ -8,193 +8,16 @@ GenericName=Folder Sync
Icon=@APPLICATION_ICON_NAME@
Keywords=@APPLICATION_NAME@;syncing;file;sharing;
X-GNOME-Autostart-Delay=3
# Translations
MimeType=application/vnd.@APPLICATION_EXECUTABLE@;
Actions=Quit;
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
[Desktop Action Quit]
Exec=@APPLICATION_EXECUTABLE@ --quit
Name=Quit @APPLICATION_NAME@
Icon=@APPLICATION_EXECUTABLE@
# Translations

View File

@@ -8,193 +8,16 @@ GenericName=Folder Sync
Icon=@APPLICATION_ICON_NAME@
Keywords=@APPLICATION_NAME@;syncing;file;sharing;
X-GNOME-Autostart-Delay=3
# Translations
MimeType=application/vnd.@APPLICATION_EXECUTABLE@;
Actions=Quit;
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
[Desktop Action Quit]
Exec=@APPLICATION_EXECUTABLE@ --quit
Name=Quit @APPLICATION_NAME@
Icon=@APPLICATION_EXECUTABLE@
# Translations

View File

@@ -8,193 +8,16 @@ GenericName=Folder Sync
Icon=@APPLICATION_ICON_NAME@
Keywords=@APPLICATION_NAME@;syncing;file;sharing;
X-GNOME-Autostart-Delay=3
# Translations
MimeType=application/vnd.@APPLICATION_EXECUTABLE@;
Actions=Quit;
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
[Desktop Action Quit]
Exec=@APPLICATION_EXECUTABLE@ --quit
Name=Quit @APPLICATION_NAME@
Icon=@APPLICATION_EXECUTABLE@
# Translations

View File

@@ -0,0 +1,27 @@
[Desktop Entry]
Categories=Utility;X-SuSE-SyncUtility;
Type=Application
Exec=@APPLICATION_EXECUTABLE@
Name=@APPLICATION_NAME@ desktop sync client
Comment=@APPLICATION_NAME@ desktop synchronization client
GenericName=Folder Sync
Icon=@APPLICATION_ICON_NAME@
Keywords=@APPLICATION_NAME@;syncing;file;sharing;
X-GNOME-Autostart-Delay=3
MimeType=application/vnd.@APPLICATION_EXECUTABLE@;
Actions=Quit;
# Translations
[Desktop Action Quit]
Exec=@APPLICATION_EXECUTABLE@ --quit
Name=Quit @APPLICATION_NAME@
Icon=@APPLICATION_EXECUTABLE@
# Translations
Icon[zh_HK]=@APPLICATION_ICON_NAME@
Name[zh_HK]= @APPLICATION_NAME@ 桌面同步客戶端
Comment[zh_HK]= @APPLICATION_NAME@ 桌面同步客戶端
GenericName[zh_HK]=資料夾同步

View File

@@ -8,193 +8,16 @@ GenericName=Folder Sync
Icon=@APPLICATION_ICON_NAME@
Keywords=@APPLICATION_NAME@;syncing;file;sharing;
X-GNOME-Autostart-Delay=3
# Translations
MimeType=application/vnd.@APPLICATION_EXECUTABLE@;
Actions=Quit;
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
[Desktop Action Quit]
Exec=@APPLICATION_EXECUTABLE@ --quit
Name=Quit @APPLICATION_NAME@
Icon=@APPLICATION_EXECUTABLE@
# Translations

View File

@@ -6,6 +6,7 @@ set( APPLICATION_VENDOR "Nextcloud GmbH" )
set( APPLICATION_UPDATE_URL "https://updates.nextcloud.org/client/" CACHE STRING "URL for updater" )
set( APPLICATION_HELP_URL "" CACHE STRING "URL for the help menu" )
set( APPLICATION_ICON_NAME "Nextcloud" )
set( APPLICATION_ICON_SET "SVG" )
set( APPLICATION_SERVER_URL "" CACHE STRING "URL for the server to use. If entered, the UI field will be pre-filled with it" )
set( APPLICATION_SERVER_URL_ENFORCE ON ) # If set and APPLICATION_SERVER_URL is defined, the server can only connect to the pre-defined URL
set( APPLICATION_REV_DOMAIN "com.nextcloud.desktopclient" )
@@ -34,7 +35,7 @@ option( WITH_PROVIDERS "Build with providers list" ON )
## Theming options
set( APPLICATION_WIZARD_HEADER_BACKGROUND_COLOR "#0082c9" CACHE STRING "Hex color of the wizard header background")
set( APPLICATION_WIZARD_HEADER_TITLE_COLOR "#ffffff" CACHE STRING "Hex color of the text in the wizard header")
option( APPLICATION_WIZARD_USE_CUSTOM_LOGO "Use the logo from ':/client/theme/colored/wizard_logo.png' else the default application icon is used" ON )
option( APPLICATION_WIZARD_USE_CUSTOM_LOGO "Use the logo from ':/client/theme/colored/wizard_logo.(png|svg)' else the default application icon is used" ON )
#

View File

@@ -1,6 +1,6 @@
set( MIRALL_VERSION_MAJOR 3 )
set( MIRALL_VERSION_MINOR 1 )
set( MIRALL_VERSION_PATCH 0 )
set( MIRALL_VERSION_PATCH 3 )
set( MIRALL_VERSION_YEAR 2020 )
set( MIRALL_SOVERSION 0 )

View File

@@ -15,10 +15,10 @@ OBS_PROJECT_BETA=home:ivaradi:beta
OBS_PACKAGE=nextcloud-desktop
if test "${DRONE_TARGET_BRANCH}" = "stable-2.6"; then
UBUNTU_DISTRIBUTIONS="bionic focal groovy"
UBUNTU_DISTRIBUTIONS="bionic focal groovy hirsute"
DEBIAN_DISTRIBUTIONS="buster stretch testing"
else
UBUNTU_DISTRIBUTIONS="focal groovy"
UBUNTU_DISTRIBUTIONS="focal groovy hirsute"
DEBIAN_DISTRIBUTIONS="testing"
fi

View File

@@ -20,6 +20,7 @@
#cmakedefine APPLICATION_UPDATE_URL "@APPLICATION_UPDATE_URL@"
#cmakedefine APPLICATION_HELP_URL "@APPLICATION_HELP_URL@"
#cmakedefine APPLICATION_ICON_NAME "@APPLICATION_ICON_NAME@"
#cmakedefine APPLICATION_ICON_SET "@APPLICATION_ICON_SET@"
#cmakedefine APPLICATION_SERVER_URL "@APPLICATION_SERVER_URL@"
#cmakedefine APPLICATION_SERVER_URL_ENFORCE "@APPLICATION_SERVER_URL_ENFORCE@"
#cmakedefine LINUX_APPLICATION_ID "@LINUX_APPLICATION_ID@"

View File

@@ -18,6 +18,7 @@
*/
#include <QStandardPaths>
#include <QtGlobal>
namespace OCC {
@@ -71,12 +72,18 @@ void setLaunchOnStartup_private(const QString &appName, const QString &guiName,
qCWarning(lcUtility) << "Could not write auto start entry" << desktopFileLocation;
return;
}
// When running inside an AppImage, we need to set the path to the
// AppImage instead of the path to the executable
const QString appImagePath = qEnvironmentVariable("APPIMAGE");
const bool runningInsideAppImage = !appImagePath.isNull() && QFile::exists(appImagePath);
const QString executablePath = runningInsideAppImage ? appImagePath : QCoreApplication::applicationFilePath();
QTextStream ts(&iniFile);
ts.setCodec("UTF-8");
ts << QLatin1String("[Desktop Entry]") << endl
<< QLatin1String("Name=") << guiName << endl
<< QLatin1String("GenericName=") << QLatin1String("File Synchronizer") << endl
<< QLatin1String("Exec=") << QCoreApplication::applicationFilePath() << " --background" << endl
<< QLatin1String("Exec=\"") << executablePath << "\" --background" << endl
<< QLatin1String("Terminal=") << "false" << endl
<< QLatin1String("Icon=") << APPLICATION_ICON_NAME << endl
<< QLatin1String("Categories=") << QLatin1String("Network") << endl

View File

@@ -22,6 +22,7 @@
#include "folderstatusmodel.h"
#include "folderstatusdelegate.h"
#include "common/utility.h"
#include "guiutility.h"
#include "application.h"
#include "configfile.h"
#include "account.h"
@@ -208,9 +209,6 @@ AccountSettings::AccountSettings(AccountState *accountState, QWidget *parent)
_ui->encryptionMessage->hide();
}
connect(UserModel::instance(), &UserModel::addAccount,
this, &AccountSettings::slotOpenAccountWizard);
customizeStyle();
}
@@ -246,17 +244,6 @@ QString AccountSettings::selectedFolderAlias() const
return _model->data(selected, FolderStatusDelegate::FolderAliasRole).toString();
}
void AccountSettings::slotOpenAccountWizard()
{
// We can't call isSystemTrayAvailable with appmenu-qt5 because it breaks the systemtray
// (issue #4693, #4944)
if (qgetenv("QT_QPA_PLATFORMTHEME") == "appmenu-qt5" || QSystemTrayIcon::isSystemTrayAvailable()) {
topLevelWidget()->close();
}
OwncloudSetupWizard::runWizard(qApp, SLOT(slotownCloudWizardDone(int)), nullptr);
}
void AccountSettings::slotToggleSignInState()
{
if (_accountState->isSignedOut()) {
@@ -719,8 +706,9 @@ void AccountSettings::slotForceSyncCurrentFolder()
void AccountSettings::slotOpenOC()
{
if (_OCUrl.isValid())
QDesktopServices::openUrl(_OCUrl);
if (_OCUrl.isValid()) {
Utility::openBrowser(_OCUrl);
}
}
void AccountSettings::slotUpdateQuota(qint64 total, qint64 used)

View File

@@ -89,7 +89,6 @@ protected slots:
void slotFolderWizardRejected();
void slotDeleteAccount();
void slotToggleSignInState();
void slotOpenAccountWizard();
void refreshSelectiveSyncStatus();
void slotMarkSubfolderEncrypted(const FolderStatusModel::SubFolderInfo* folderInfo);
void slotSubfolderContextMenuRequested(const QModelIndex& idx, const QPoint& point);

View File

@@ -25,6 +25,7 @@
#include "theme.h"
#include "networkjobs.h"
#include "configfile.h"
#include "guiutility.h"
namespace OCC {
@@ -146,7 +147,7 @@ void Flow2Auth::fetchNewToken(const TokenAction action)
{
case actionOpenBrowser:
// Try to open Browser
if (!QDesktopServices::openUrl(authorisationLink())) {
if (!Utility::openBrowser(authorisationLink())) {
// We cannot open the browser, then we claim we don't support Flow2Auth.
// Our UI callee will ask the user to copy and open the link.
emit result(NotSupported);

View File

@@ -22,6 +22,7 @@
#include <QJsonDocument>
#include "theme.h"
#include "networkjobs.h"
#include "guiutility.h"
namespace OCC {
@@ -165,7 +166,7 @@ QUrl OAuth::authorisationLink() const
bool OAuth::openBrowser()
{
if (!QDesktopServices::openUrl(authorisationLink())) {
if (!Utility::openBrowser(authorisationLink())) {
// We cannot open the browser, then we claim we don't support OAuth.
emit result(NotSupported, QString());
return false;

View File

@@ -24,6 +24,7 @@
#include "filesystem.h"
#include "lockwatcher.h"
#include "common/asserts.h"
#include <pushnotifications.h>
#include <syncengine.h>
#ifdef Q_OS_MAC
@@ -77,6 +78,8 @@ FolderMan::FolderMan(QObject *parent)
connect(_lockWatcher.data(), &LockWatcher::fileUnlocked,
this, &FolderMan::slotWatchedFileUnlocked);
connect(this, &FolderMan::folderListChanged, this, &FolderMan::slotSetupPushNotifications);
}
FolderMan *FolderMan::instance()
@@ -753,34 +756,82 @@ void FolderMan::slotStartScheduledFolderSync()
}
}
bool FolderMan::pushNotificationsFilesReady(Account *account)
{
const auto pushNotifications = account->pushNotifications();
const auto pushFilesAvailable = account->capabilities().availablePushNotifications() & PushNotificationType::Files;
return pushFilesAvailable && pushNotifications && pushNotifications->isReady();
}
void FolderMan::slotEtagPollTimerTimeout()
{
ConfigFile cfg;
auto polltime = cfg.remotePollInterval();
qCInfo(lcFolderMan) << "Etag poll timer timeout";
for (Folder *f : qAsConst(_folderMap)) {
if (!f) {
continue;
}
if (_currentSyncFolder == f) {
continue;
}
if (_scheduledFolders.contains(f)) {
continue;
}
if (_disabledFolders.contains(f)) {
continue;
}
if (f->etagJob() || f->isBusy() || !f->canSync()) {
continue;
}
if (f->msecSinceLastSync() < polltime) {
continue;
}
QMetaObject::invokeMethod(f, "slotRunEtagJob", Qt::QueuedConnection);
const auto folderMapValues = _folderMap.values();
qCInfo(lcFolderMan) << "Folders to sync:" << folderMapValues.size();
QList<Folder *> foldersToRun;
// Some folders need not to be checked because they use the push notifications
std::copy_if(folderMapValues.begin(), folderMapValues.end(), std::back_inserter(foldersToRun), [this](Folder *folder) -> bool {
const auto account = folder->accountState()->account();
const auto capabilities = account->capabilities();
const auto pushNotifications = account->pushNotifications();
return !pushNotificationsFilesReady(account.data());
});
qCInfo(lcFolderMan) << "Number of folders that don't use push notifications:" << foldersToRun.size();
runEtagJobsIfPossible(foldersToRun);
}
void FolderMan::runEtagJobsIfPossible(const QList<Folder *> &folderMap)
{
for (auto folder : folderMap) {
runEtagJobIfPossible(folder);
}
}
void FolderMan::runEtagJobIfPossible(Folder *folder)
{
const ConfigFile cfg;
const auto polltime = cfg.remotePollInterval();
qCInfo(lcFolderMan) << "Run etag job on folder" << folder;
if (!folder) {
return;
}
if (_currentSyncFolder == folder) {
qCInfo(lcFolderMan) << "Can not run etag job: Sync is running";
return;
}
if (_scheduledFolders.contains(folder)) {
qCInfo(lcFolderMan) << "Can not run etag job: Folder is alreday scheduled";
return;
}
if (_disabledFolders.contains(folder)) {
qCInfo(lcFolderMan) << "Can not run etag job: Folder is disabled";
return;
}
if (folder->etagJob() || folder->isBusy() || !folder->canSync()) {
qCInfo(lcFolderMan) << "Can not run etag job: Folder is busy";
return;
}
// When not using push notifications, make sure polltime is reached
if (!pushNotificationsFilesReady(folder->accountState()->account().data())) {
if (folder->msecSinceLastSync() < polltime) {
qCInfo(lcFolderMan) << "Can not run etag job: Polltime not reached";
return;
}
}
QMetaObject::invokeMethod(folder, "slotRunEtagJob", Qt::QueuedConnection);
}
void FolderMan::slotRemoveFoldersForAccount(AccountState *accountState)
{
QVarLengthArray<Folder *, 16> foldersToRemove;
@@ -1505,4 +1556,42 @@ void FolderMan::restartApplication()
}
}
void FolderMan::slotSetupPushNotifications(const Folder::Map &folderMap)
{
for (auto folder : folderMap) {
const auto account = folder->accountState()->account();
// See if the account already provides the PushNotifications object and if yes connect to it.
// If we can't connect at this point, the signals will be connected in slotPushNotificationsReady()
// after the PushNotification object emitted the ready signal
slotConnectToPushNotifications(account.data());
connect(account.data(), &Account::pushNotificationsReady, this, &FolderMan::slotConnectToPushNotifications, Qt::UniqueConnection);
}
}
void FolderMan::slotProcessFilesPushNotification(Account *account)
{
qCInfo(lcFolderMan) << "Got files push notification for account" << account;
for (auto folder : _folderMap) {
// Just run on the folders that belong to this account
if (folder->accountState()->account() != account) {
continue;
}
qCInfo(lcFolderMan) << "Schedule folder" << folder << "for sync";
scheduleFolder(folder);
}
}
void FolderMan::slotConnectToPushNotifications(Account *account)
{
const auto pushNotifications = account->pushNotifications();
if (pushNotificationsFilesReady(account)) {
qCInfo(lcFolderMan) << "Push notifications ready";
connect(pushNotifications, &PushNotifications::filesChanged, this, &FolderMan::slotProcessFilesPushNotification, Qt::UniqueConnection);
}
}
} // namespace OCC

View File

@@ -276,6 +276,10 @@ private slots:
*/
void slotScheduleFolderByTime();
void slotSetupPushNotifications(const Folder::Map &);
void slotProcessFilesPushNotification(Account *account);
void slotConnectToPushNotifications(Account *account);
private:
/** Adds a new folder, does not add it to the account settings and
* does not set an account on the new folder.
@@ -301,6 +305,11 @@ private:
void setupFoldersHelper(QSettings &settings, AccountStatePtr account, bool backwardsCompatible);
void runEtagJobsIfPossible(const QList<Folder *> &folderMap);
void runEtagJobIfPossible(Folder *folder);
bool pushNotificationsFilesReady(Account *account);
QSet<Folder *> _disabledFolders;
Folder::Map _folderMap;
QString _folderConfigPath;

View File

@@ -27,6 +27,17 @@ Q_LOGGING_CATEGORY(lcUtility, "nextcloud.gui.utility", QtInfoMsg)
bool Utility::openBrowser(const QUrl &url, QWidget *errorWidgetParent)
{
const QStringList allowedUrlSchemes = {
"http",
"https",
"oauthtest"
};
if (!allowedUrlSchemes.contains(url.scheme())) {
qCWarning(lcUtility) << "URL format is not supported, or it has been compromised for:" << url.toString();
return false;
}
if (!QDesktopServices::openUrl(url)) {
if (errorWidgetParent) {
QMessageBox::warning(

View File

@@ -26,7 +26,7 @@ namespace Utility {
*
* If launching the browser fails, display a message.
*/
bool openBrowser(const QUrl &url, QWidget *errorWidgetParent);
bool openBrowser(const QUrl &url, QWidget *errorWidgetParent = nullptr);
/** Start composing a new email message.
*

View File

@@ -28,6 +28,7 @@
#include "accountmanager.h"
#include "common/syncjournalfilerecord.h"
#include "creds/abstractcredentials.h"
#include "guiutility.h"
#ifdef WITH_LIBCLOUDPROVIDERS
#include "cloudproviders/cloudprovidermanager.h"
#endif
@@ -570,7 +571,7 @@ void ownCloudGui::slotToggleLogBrowser()
void ownCloudGui::slotOpenOwnCloud()
{
if (auto account = qvariant_cast<AccountPtr>(sender()->property(propertyAccountC))) {
QDesktopServices::openUrl(account->url());
Utility::openBrowser(account->url());
}
}

View File

@@ -499,7 +499,7 @@ void SocketApi::command_EDIT(const QString &localFile, SocketListener *listener)
auto url = QUrl(data.value("url").toString());
if(!url.isEmpty())
Utility::openBrowser(url, nullptr);
Utility::openBrowser(url);
});
job->start();
}
@@ -711,7 +711,9 @@ void SocketApi::command_RESOLVE_CONFLICT(const QString &localFile, SocketListene
dialog.setBaseFilename(baseName);
dialog.setLocalVersionFilename(conflictedPath);
dialog.setRemoteVersionFilename(basePath);
dialog.exec();
if (dialog.exec() == ConflictDialog::Accepted) {
fileData.folder->scheduleThisFolderSoon();
}
#endif
}
@@ -770,7 +772,7 @@ void SocketApi::emailPrivateLink(const QString &link)
void OCC::SocketApi::openPrivateLink(const QString &link)
{
Utility::openBrowser(link, nullptr);
Utility::openBrowser(link);
}
void SocketApi::command_GET_STRINGS(const QString &argument, SocketListener *listener)

View File

@@ -119,6 +119,8 @@ Systray::Systray()
connect(UserModel::instance(), &UserModel::newUserSelected,
this, &Systray::slotNewUserSelected);
connect(UserModel::instance(), &UserModel::addAccount,
this, &Systray::openAccountWizard);
connect(AccountManager::instance(), &AccountManager::accountAdded,
this, &Systray::showWindow);

View File

@@ -26,6 +26,8 @@
#include "folderman.h"
#include "iconjob.h"
#include "accessmanager.h"
#include "owncloudgui.h"
#include "guiutility.h"
#include "ActivityData.h"
#include "ActivityListModel.h"
@@ -417,7 +419,7 @@ void ActivityListModel::removeActivityFromActivityList(Activity activity)
}
}
void ActivityListModel::triggerDefaultAction(int activityIndex) const
void ActivityListModel::triggerDefaultAction(int activityIndex)
{
if (activityIndex < 0 || activityIndex >= _finalList.size()) {
qCWarning(lcActivity) << "Couldn't trigger default action at index" << activityIndex << "/ final list size:" << _finalList.size();
@@ -444,11 +446,19 @@ void ActivityListModel::triggerDefaultAction(int activityIndex) const
const auto baseName = QFileInfo(basePath).fileName();
ConflictDialog dialog;
dialog.setBaseFilename(baseName);
dialog.setLocalVersionFilename(conflictedPath);
dialog.setRemoteVersionFilename(basePath);
dialog.exec();
if (!_currentConflictDialog.isNull()) {
_currentConflictDialog->close();
}
_currentConflictDialog = new ConflictDialog;
_currentConflictDialog->setBaseFilename(baseName);
_currentConflictDialog->setLocalVersionFilename(conflictedPath);
_currentConflictDialog->setRemoteVersionFilename(basePath);
_currentConflictDialog->setAttribute(Qt::WA_DeleteOnClose);
connect(_currentConflictDialog, &ConflictDialog::accepted, folder, [folder]() {
folder->scheduleThisFolderSoon();
});
_currentConflictDialog->open();
ownCloudGui::raiseDialog(_currentConflictDialog);
return;
}
@@ -456,7 +466,7 @@ void ActivityListModel::triggerDefaultAction(int activityIndex) const
QDesktopServices::openUrl(path);
} else {
const auto link = data(modelIndex, LinkRole).toUrl();
QDesktopServices::openUrl(link);
Utility::openBrowser(link);
}
}
@@ -477,7 +487,7 @@ void ActivityListModel::triggerAction(int activityIndex, int actionIndex)
const auto action = activity._links[actionIndex];
if (action._verb == "WEB") {
QDesktopServices::openUrl(QUrl(action._link));
Utility::openBrowser(QUrl(action._link));
return;
}

View File

@@ -26,6 +26,7 @@ namespace OCC {
Q_DECLARE_LOGGING_CATEGORY(lcActivity)
class AccountState;
class ConflictDialog;
/**
* @brief The ActivityListModel
@@ -74,7 +75,7 @@ public:
void removeActivityFromActivityList(int row);
void removeActivityFromActivityList(Activity activity);
Q_INVOKABLE void triggerDefaultAction(int activityIndex) const;
Q_INVOKABLE void triggerDefaultAction(int activityIndex);
Q_INVOKABLE void triggerAction(int activityIndex, int actionIndex);
public slots:
@@ -113,6 +114,8 @@ private:
int _maxActivities = 100;
int _maxActivitiesDays = 30;
bool _showMoreActivitiesAvailableEntry = false;
QPointer<ConflictDialog> _currentConflictDialog;
};
}

View File

@@ -18,7 +18,7 @@ Button {
icon.width: Style.headerButtonIconSize
icon.height: Style.headerButtonIconSize
icon.color: "transparent"
icon.color: Style.ncTextColor
Layout.alignment: Qt.AlignRight
Layout.preferredWidth: Style.trayWindowHeaderHeight

View File

@@ -3,11 +3,13 @@
#include "accountmanager.h"
#include "owncloudgui.h"
#include <pushnotifications.h>
#include "syncengine.h"
#include "ocsjob.h"
#include "configfile.h"
#include "notificationconfirmjob.h"
#include "logger.h"
#include "guiutility.h"
#include <QDesktopServices>
#include <QIcon>
@@ -40,7 +42,7 @@ User::User(AccountStatePtr &account, const bool &isCurrent, QObject *parent)
this, &User::slotRefresh);
connect(_account.data(), &AccountState::stateChanged,
[=]() { if (isConnected()) {slotRefresh();} });
[=]() { if (isConnected()) {slotRefreshImmediately();} });
connect(_account.data(), &AccountState::stateChanged, this, &User::accountStateChanged);
connect(_account.data(), &AccountState::hasFetchedNavigationApps,
this, &User::slotRebuildNavigationAppList);
@@ -105,19 +107,90 @@ void User::slotBuildNotificationDisplay(const ActivityList &list)
void User::setNotificationRefreshInterval(std::chrono::milliseconds interval)
{
qCDebug(lcActivity) << "Starting Notification refresh timer with " << interval.count() / 1000 << " sec interval";
_notificationCheckTimer.start(interval.count());
if (!checkPushNotificationsAreReady()) {
qCDebug(lcActivity) << "Starting Notification refresh timer with " << interval.count() / 1000 << " sec interval";
_notificationCheckTimer.start(interval.count());
}
}
void User::slotPushNotificationsReady()
{
qCInfo(lcActivity) << "Push notifications are ready";
if (_notificationCheckTimer.isActive()) {
// as we are now able to use push notifications - let's stop the polling timer
_notificationCheckTimer.stop();
}
connectPushNotifications();
}
void User::slotDisconnectPushNotifications()
{
disconnect(_account->account()->pushNotifications(), &PushNotifications::notificationsChanged, this, &User::slotReceivedPushNotification);
disconnect(_account->account()->pushNotifications(), &PushNotifications::activitiesChanged, this, &User::slotReceivedPushActivity);
disconnect(_account->account().data(), &Account::pushNotificationsDisabled, this, &User::slotDisconnectPushNotifications);
// connection to WebSocket may have dropped or an error occured, so we need to bring back the polling until we have re-established the connection
setNotificationRefreshInterval(ConfigFile().notificationRefreshInterval());
}
void User::slotReceivedPushNotification(Account *account)
{
if (account->id() == _account->account()->id()) {
slotRefreshNotifications();
}
}
void User::slotReceivedPushActivity(Account *account)
{
if (account->id() == _account->account()->id()) {
slotRefreshActivities();
}
}
void User::connectPushNotifications() const
{
connect(_account->account().data(), &Account::pushNotificationsDisabled, this, &User::slotDisconnectPushNotifications, Qt::UniqueConnection);
connect(_account->account()->pushNotifications(), &PushNotifications::notificationsChanged, this, &User::slotReceivedPushNotification, Qt::UniqueConnection);
connect(_account->account()->pushNotifications(), &PushNotifications::activitiesChanged, this, &User::slotReceivedPushActivity, Qt::UniqueConnection);
}
bool User::checkPushNotificationsAreReady() const
{
const auto pushNotifications = _account->account()->pushNotifications();
const auto pushActivitiesAvailable = _account->account()->capabilities().availablePushNotifications() & PushNotificationType::Activities;
const auto pushNotificationsAvailable = _account->account()->capabilities().availablePushNotifications() & PushNotificationType::Notifications;
const auto pushActivitiesAndNotificationsAvailable = pushActivitiesAvailable && pushNotificationsAvailable;
if (pushActivitiesAndNotificationsAvailable && pushNotifications && pushNotifications->isReady()) {
connectPushNotifications();
return true;
} else {
connect(_account->account().data(), &Account::pushNotificationsReady, this, &User::slotPushNotificationsReady, Qt::UniqueConnection);
return false;
}
}
void User::slotRefreshImmediately() {
if (_account.data() && _account.data()->isConnected()) {
this->slotRefreshActivities();
slotRefreshActivities();
}
this->slotRefreshNotifications();
slotRefreshNotifications();
}
void User::slotRefresh()
{
if (checkPushNotificationsAreReady()) {
// we are relying on WebSocket push notifications - ignore refresh attempts from UI
_timeSinceLastCheck[_account.data()].invalidate();
return;
}
// QElapsedTimer isn't actually constructed as invalid.
if (!_timeSinceLastCheck.contains(_account.data())) {
_timeSinceLastCheck[_account.data()].invalidate();
@@ -131,9 +204,9 @@ void User::slotRefresh()
}
if (_account.data() && _account.data()->isConnected()) {
if (!timer.isValid()) {
this->slotRefreshActivities();
slotRefreshActivities();
}
this->slotRefreshNotifications();
slotRefreshNotifications();
timer.start();
}
}
@@ -572,7 +645,7 @@ Q_INVOKABLE int UserModel::currentUserId() const
Q_INVOKABLE bool UserModel::isUserConnected(const int &id)
{
if (_users.isEmpty())
if (id < 0 || id >= _users.size())
return false;
return _users[id]->isConnected();
@@ -580,7 +653,7 @@ Q_INVOKABLE bool UserModel::isUserConnected(const int &id)
QImage UserModel::avatarById(const int &id)
{
if (_users.isEmpty())
if (id < 0 || id >= _users.size())
return {};
return _users[id]->avatar();
@@ -588,7 +661,7 @@ QImage UserModel::avatarById(const int &id)
Q_INVOKABLE QString UserModel::currentUserServer()
{
if (_users.isEmpty())
if (_currentUserId < 0 || _currentUserId >= _users.size())
return {};
return _users[_currentUserId]->server();
@@ -634,7 +707,7 @@ int UserModel::currentUserIndex()
Q_INVOKABLE void UserModel::openCurrentAccountLocalFolder()
{
if (_users.isEmpty())
if (_currentUserId < 0 || _currentUserId >= _users.size())
return;
_users[_currentUserId]->openLocalFolder();
@@ -647,7 +720,7 @@ Q_INVOKABLE void UserModel::openCurrentAccountTalk()
const auto talkApp = currentUser()->talkApp();
if (talkApp) {
QDesktopServices::openUrl(talkApp->url());
Utility::openBrowser(talkApp->url());
} else {
qCWarning(lcActivity) << "The Talk app is not enabled on" << currentUser()->server();
}
@@ -655,19 +728,20 @@ Q_INVOKABLE void UserModel::openCurrentAccountTalk()
Q_INVOKABLE void UserModel::openCurrentAccountServer()
{
if (_users.isEmpty())
if (_currentUserId < 0 || _currentUserId >= _users.size())
return;
QString url = _users[_currentUserId]->server(false);
if (!(url.contains("http://") || url.contains("https://"))) {
if (!url.startsWith("http://") && !url.startsWith("https://")) {
url = "https://" + _users[_currentUserId]->server(false);
}
QDesktopServices::openUrl(QUrl(url));
QDesktopServices::openUrl(url);
}
Q_INVOKABLE void UserModel::switchCurrentUser(const int &id)
{
if (_users.isEmpty())
if (_currentUserId < 0 || _currentUserId >= _users.size())
return;
disconnect(_users[_currentUserId], &User::accountStateChanged, this, &UserModel::refreshCurrentUserGui);
@@ -681,7 +755,7 @@ Q_INVOKABLE void UserModel::switchCurrentUser(const int &id)
Q_INVOKABLE void UserModel::login(const int &id)
{
if (_users.isEmpty())
if (id < 0 || id >= _users.size())
return;
_users[id]->login();
@@ -690,7 +764,7 @@ Q_INVOKABLE void UserModel::login(const int &id)
Q_INVOKABLE void UserModel::logout(const int &id)
{
if (_users.isEmpty())
if (id < 0 || id >= _users.size())
return;
_users[id]->logout();
@@ -699,7 +773,7 @@ Q_INVOKABLE void UserModel::logout(const int &id)
Q_INVOKABLE void UserModel::removeAccount(const int &id)
{
if (_users.isEmpty())
if (id < 0 || id >= _users.size())
return;
QMessageBox messageBox(QMessageBox::Question,
@@ -777,7 +851,7 @@ QHash<int, QByteArray> UserModel::roleNames() const
ActivityListModel *UserModel::currentActivityModel()
{
if (_users.isEmpty())
if (currentUserIndex() < 0 || currentUserIndex() >= _users.size())
return nullptr;
return _users[currentUserIndex()]->getActivityModel();
@@ -785,7 +859,7 @@ ActivityListModel *UserModel::currentActivityModel()
bool UserModel::currentUserHasActivities()
{
if (_users.isEmpty())
if (currentUserIndex() < 0 || currentUserIndex() >= _users.size())
return false;
return _users[currentUserIndex()]->hasActivities();
@@ -793,7 +867,7 @@ bool UserModel::currentUserHasActivities()
bool UserModel::currentUserHasLocalFolder()
{
if (_users.isEmpty())
if (currentUserIndex() < 0 || currentUserIndex() >= _users.size())
return false;
return _users[currentUserIndex()]->getFolder() != nullptr;
@@ -801,21 +875,23 @@ bool UserModel::currentUserHasLocalFolder()
void UserModel::fetchCurrentActivityModel()
{
if (!_users.isEmpty())
_users[currentUserId()]->slotRefresh();
if (currentUserId() < 0 || currentUserId() >= _users.size())
return;
_users[currentUserId()]->slotRefresh();
}
AccountAppList UserModel::appList() const
{
if (_users.isEmpty())
return AccountAppList();
if (_currentUserId < 0 || _currentUserId >= _users.size())
return {};
return _users[_currentUserId]->appList();
}
User *UserModel::currentUser() const
{
if (_users.isEmpty())
if (currentUserId() < 0 || currentUserId() >= _users.size())
return nullptr;
return _users[currentUserId()];
@@ -909,7 +985,7 @@ void UserAppsModel::buildAppList()
void UserAppsModel::openAppUrl(const QUrl &url)
{
QDesktopServices::openUrl(url);
Utility::openBrowser(url);
}
int UserAppsModel::rowCount(const QModelIndex &parent) const

View File

@@ -71,6 +71,15 @@ public slots:
void setNotificationRefreshInterval(std::chrono::milliseconds interval);
void slotRebuildNavigationAppList();
private:
void slotPushNotificationsReady();
void slotDisconnectPushNotifications();
void slotReceivedPushNotification(Account *account);
void slotReceivedPushActivity(Account *account);
void connectPushNotifications() const;
bool checkPushNotificationsAreReady() const;
private:
AccountStatePtr _account;
bool _isCurrentUser;

View File

@@ -388,13 +388,19 @@ Window {
}
}
Image {
Layout.alignment: Qt.AlignRight
verticalAlignment: Qt.AlignCenter
Layout.margins: Style.accountDropDownCaretMargin
source: "qrc:///client/theme/white/caret-down.svg"
sourceSize.width: Style.accountDropDownCaretSize
sourceSize.height: Style.accountDropDownCaretSize
ColorOverlay {
cached: true
color: Style.ncTextColor
width: source.width
height: source.height
source: Image {
Layout.alignment: Qt.AlignRight
verticalAlignment: Qt.AlignCenter
Layout.margins: Style.accountDropDownCaretMargin
source: "qrc:///client/theme/white/caret-down.svg"
sourceSize.width: Style.accountDropDownCaretSize
sourceSize.height: Style.accountDropDownCaretSize
}
}
}
}

View File

@@ -17,6 +17,7 @@
#include <QDir>
#include <QUrl>
#include "guiutility.h"
#include "wizard/owncloudwizardresultpage.h"
#include "wizard/owncloudwizardcommon.h"
#include "theme.h"
@@ -93,7 +94,7 @@ void OwncloudWizardResultPage::slotOpenServer()
{
Theme *theme = Theme::instance();
QUrl url = QUrl(field("OCUrl").toString() + theme->wizardUrlPostfix());
QDesktopServices::openUrl(url);
Utility::openBrowser(url);
}
} // namespace OCC

View File

@@ -16,6 +16,7 @@
#include <QWebEngineCertificateError>
#include <QMessageBox>
#include "guiutility.h"
#include "common/utility.h"
namespace OCC {
@@ -51,9 +52,6 @@ public:
protected:
bool certificateError(const QWebEngineCertificateError &certificateError) override;
private:
QUrl _rootUrl;
};
// We need a separate class here, since we cannot simply return the same WebEnginePage object
@@ -190,15 +188,10 @@ QWebEnginePage * WebEnginePage::createWindow(QWebEnginePage::WebWindowType type)
void WebEnginePage::setUrl(const QUrl &url) {
QWebEnginePage::setUrl(url);
_rootUrl = url;
}
bool WebEnginePage::certificateError(const QWebEngineCertificateError &certificateError) {
if (certificateError.error() == QWebEngineCertificateError::CertificateAuthorityInvalid &&
certificateError.url().host() == _rootUrl.host()) {
return true;
}
bool WebEnginePage::certificateError(const QWebEngineCertificateError &certificateError)
{
/**
* TODO properly improve this.
* The certificate should be displayed.
@@ -227,7 +220,7 @@ bool ExternalWebEnginePage::acceptNavigationRequest(const QUrl &url, QWebEngineP
{
Q_UNUSED(type);
Q_UNUSED(isMainFrame);
QDesktopServices::openUrl(url);
Utility::openBrowser(url);
return false;
}

View File

@@ -17,6 +17,7 @@ ENDIF(${CMAKE_SYSTEM_NAME} MATCHES "FreeBSD|NetBSD|OpenBSD")
set(libsync_SRCS
account.cpp
pushnotifications.cpp
wordlist.cpp
bandwidthmanager.cpp
capabilities.cpp
@@ -91,6 +92,7 @@ IF (NOT APPLE)
)
ENDIF(NOT APPLE)
find_package(Qt5 REQUIRED COMPONENTS WebSockets)
add_library(${synclib_NAME} SHARED ${libsync_SRCS})
target_link_libraries(${synclib_NAME}
ocsync
@@ -98,6 +100,7 @@ target_link_libraries(${synclib_NAME}
OpenSSL::SSL
${OS_SPECIFIC_LINK_LIBRARIES}
Qt5::Core Qt5::Network
Qt5::WebSockets
)
if (NOT TOKEN_AUTH_ONLY)

View File

@@ -20,6 +20,7 @@
#include "creds/abstractcredentials.h"
#include "capabilities.h"
#include "theme.h"
#include "pushnotifications.h"
#include "common/asserts.h"
#include "clientsideencryption.h"
@@ -56,6 +57,7 @@ Account::Account(QObject *parent)
, _davPath(Theme::instance()->webDavPath())
{
qRegisterMetaType<AccountPtr>("AccountPtr");
qRegisterMetaType<Account *>("Account*");
}
AccountPtr Account::create()
@@ -198,6 +200,33 @@ void Account::setCredentials(AbstractCredentials *cred)
this, &Account::slotCredentialsFetched);
connect(_credentials.data(), &AbstractCredentials::asked,
this, &Account::slotCredentialsAsked);
trySetupPushNotifications();
}
void Account::trySetupPushNotifications()
{
if (_capabilities.availablePushNotifications() != PushNotificationType::None) {
qCInfo(lcAccount) << "Try to setup push notifications";
if (!_pushNotifications) {
_pushNotifications = new PushNotifications(this, this);
connect(_pushNotifications, &PushNotifications::ready, this, [this]() { emit pushNotificationsReady(this); });
const auto deletePushNotifications = [this]() {
qCInfo(lcAccount) << "Delete push notifications object because authentication failed or connection lost";
_pushNotifications->deleteLater();
_pushNotifications = nullptr;
emit pushNotificationsDisabled(this);
};
connect(_pushNotifications, &PushNotifications::connectionLost, this, deletePushNotifications);
connect(_pushNotifications, &PushNotifications::authenticationFailed, this, deletePushNotifications);
}
// If push notifications already running it is no problem to call setup again
_pushNotifications->setup();
}
}
QUrl Account::davUrl() const
@@ -471,6 +500,8 @@ const Capabilities &Account::capabilities() const
void Account::setCapabilities(const QVariantMap &caps)
{
_capabilities = Capabilities(caps);
trySetupPushNotifications();
}
QString Account::serverVersion() const
@@ -658,4 +689,9 @@ void Account::slotDirectEditingRecieved(const QJsonDocument &json)
}
}
PushNotifications *Account::pushNotifications() const
{
return _pushNotifications;
}
} // namespace OCC

View File

@@ -54,6 +54,7 @@ class Account;
using AccountPtr = QSharedPointer<Account>;
class AccessManager;
class SimpleNetworkJob;
class PushNotifications;
/**
* @brief Reimplement this to handle SSL errors from libsync
@@ -249,6 +250,8 @@ public:
// Check for the directEditing capability
void fetchDirectEditors(const QUrl &directEditingURL, const QString &directEditingETag);
PushNotifications *pushNotifications() const;
public slots:
/// Used when forgetting credentials
void clearQNAMCache();
@@ -278,6 +281,9 @@ signals:
/// Used in RemoteWipe
void appPasswordRetrieved(QString);
void pushNotificationsReady(Account *account);
void pushNotificationsDisabled(Account *account);
protected Q_SLOTS:
void slotCredentialsFetched();
void slotCredentialsAsked();
@@ -286,6 +292,7 @@ protected Q_SLOTS:
private:
Account(QObject *parent = nullptr);
void setSharedThis(AccountPtr sharedThis);
void trySetupPushNotifications();
QWeakPointer<Account> _sharedThis;
QString _id;
@@ -330,6 +337,8 @@ private:
// Direct Editing
QString _lastDirectEditingETag;
PushNotifications *_pushNotifications = nullptr;
/* IMPORTANT - remove later - FIXME MS@2019-12-07 -->
* TODO: For "Log out" & "Remove account": Remove client CA certs and KEY!
*
@@ -349,5 +358,6 @@ private:
}
Q_DECLARE_METATYPE(OCC::AccountPtr)
Q_DECLARE_METATYPE(OCC::Account *)
#endif //SERVERCONNECTION_H

View File

@@ -16,6 +16,7 @@
#include <QVariantMap>
#include <QLoggingCategory>
#include <QUrl>
#include <QDebug>
@@ -174,6 +175,36 @@ bool Capabilities::chunkingNg() const
return _capabilities["dav"].toMap()["chunking"].toByteArray() >= "1.0";
}
PushNotificationTypes Capabilities::availablePushNotifications() const
{
if (!_capabilities.contains("notify_push")) {
return PushNotificationType::None;
}
const auto types = _capabilities["notify_push"].toMap()["type"].toStringList();
PushNotificationTypes pushNotificationTypes;
if (types.contains("files")) {
pushNotificationTypes.setFlag(PushNotificationType::Files);
}
if (types.contains("activities")) {
pushNotificationTypes.setFlag(PushNotificationType::Activities);
}
if (types.contains("notifications")) {
pushNotificationTypes.setFlag(PushNotificationType::Notifications);
}
return pushNotificationTypes;
}
QUrl Capabilities::pushNotificationsWebSocketUrl() const
{
const auto websocket = _capabilities["notify_push"].toMap()["endpoints"].toMap()["websocket"].toString();
return QUrl(websocket);
}
bool Capabilities::chunkingParallelUploadDisabled() const
{
return _capabilities["dav"].toMap()["chunkingParallelUploadDisabled"].toBool();

View File

@@ -26,6 +26,15 @@ namespace OCC {
class DirectEditor;
enum PushNotificationType {
None = 0,
Files = 1,
Activities = 2,
Notifications = 4
};
Q_DECLARE_FLAGS(PushNotificationTypes, PushNotificationType)
Q_DECLARE_OPERATORS_FOR_FLAGS(PushNotificationTypes)
/**
* @brief The Capabilities class represents the capabilities of an ownCloud
* server
@@ -48,6 +57,12 @@ public:
bool shareResharing() const;
bool chunkingNg() const;
/// Returns which kind of push notfications are available
PushNotificationTypes availablePushNotifications() const;
/// Websocket url for files push notifications if available
QUrl pushNotificationsWebSocketUrl() const;
/// disable parallel upload in chunking
bool chunkingParallelUploadDisabled() const;

View File

@@ -888,7 +888,7 @@ bool ConfigFile::monoIcons() const
bool monoDefault = false; // On Mac we want bw by default
#ifdef Q_OS_MAC
// OEM themes are not obliged to ship mono icons
monoDefault = (0 == (strcmp("ownCloud", APPLICATION_NAME)));
monoDefault = QByteArrayLiteral("Nextcloud") == QByteArrayLiteral(APPLICATION_NAME);
#endif
return settings.value(QLatin1String(monoIconsC), monoDefault).toBool();
}

View File

@@ -43,6 +43,7 @@ public:
virtual QString authType() const = 0;
virtual QString user() const = 0;
virtual QString password() const = 0;
virtual QNetworkAccessManager *createQNAM() const = 0;
/** Whether there are credentials that can be used for a connection attempt. */

View File

@@ -27,6 +27,12 @@ QString DummyCredentials::user() const
return _user;
}
QString DummyCredentials::password() const
{
Q_UNREACHABLE();
return QString();
}
QNetworkAccessManager *DummyCredentials::createQNAM() const
{
return new AccessManager;

View File

@@ -28,6 +28,7 @@ public:
QString _password;
QString authType() const override;
QString user() const override;
QString password() const override;
QNetworkAccessManager *createQNAM() const override;
bool ready() const override;
bool stillValid(QNetworkReply *reply) override;

View File

@@ -90,7 +90,7 @@ public:
void persist() override;
QString user() const override;
// the password or token
QString password() const;
QString password() const override;
void invalidateToken() override;
void forgetSensitiveData() override;
QString fetchUser();

View File

@@ -0,0 +1,197 @@
#include "pushnotifications.h"
#include "creds/abstractcredentials.h"
#include "account.h"
namespace {
static constexpr int MAX_ALLOWED_FAILED_AUTHENTICATION_ATTEMPTS = 3;
}
namespace OCC {
Q_LOGGING_CATEGORY(lcPushNotifications, "nextcloud.sync.pushnotifications", QtInfoMsg)
PushNotifications::PushNotifications(Account *account, QObject *parent)
: QObject(parent)
, _account(account)
{
}
PushNotifications::~PushNotifications()
{
closeWebSocket();
}
void PushNotifications::setup()
{
_isReady = false;
_failedAuthenticationAttemptsCount = 0;
reconnectToWebSocket();
}
void PushNotifications::reconnectToWebSocket()
{
closeWebSocket();
openWebSocket();
}
void PushNotifications::closeWebSocket()
{
if (_webSocket) {
qCInfo(lcPushNotifications) << "Close websocket";
_webSocket->close();
}
}
void PushNotifications::onWebSocketConnected()
{
qCInfo(lcPushNotifications) << "Connected to websocket";
connect(_webSocket, &QWebSocket::textMessageReceived, this, &PushNotifications::onWebSocketTextMessageReceived, Qt::UniqueConnection);
authenticateOnWebSocket();
}
void PushNotifications::authenticateOnWebSocket()
{
const auto credentials = _account->credentials();
const auto username = credentials->user();
const auto password = credentials->password();
// Authenticate
_webSocket->sendTextMessage(username);
_webSocket->sendTextMessage(password);
}
void PushNotifications::onWebSocketDisconnected()
{
qCInfo(lcPushNotifications) << "Disconnected from websocket";
}
void PushNotifications::onWebSocketTextMessageReceived(const QString &message)
{
qCInfo(lcPushNotifications) << "Received push notification:" << message;
if (message == "notify_file") {
handleNotifyFile();
} else if (message == "notify_activity") {
handleNotifyActivity();
} else if (message == "notify_notification") {
handleNotifyNotification();
} else if (message == "authenticated") {
handleAuthenticated();
} else if (message == "err: Invalid credentials") {
handleInvalidCredentials();
}
}
void PushNotifications::onWebSocketError(QAbstractSocket::SocketError error)
{
// This error gets thrown in testSetup_maxConnectionAttemptsReached_deletePushNotifications after
// the second connection attempt. I have no idea why this happens. Maybe the socket gets not closed correctly?
// I think it's fine to ignore this error.
if (error == QAbstractSocket::UnfinishedSocketOperationError) {
return;
}
qCWarning(lcPushNotifications) << "Websocket error" << error;
_isReady = false;
emit connectionLost();
}
bool PushNotifications::tryReconnectToWebSocket()
{
++_failedAuthenticationAttemptsCount;
if (_failedAuthenticationAttemptsCount >= MAX_ALLOWED_FAILED_AUTHENTICATION_ATTEMPTS) {
qCInfo(lcPushNotifications) << "Max authentication attempts reached";
return false;
}
if (!_reconnectTimer) {
_reconnectTimer = new QTimer(this);
}
_reconnectTimer->setInterval(_reconnectTimerInterval);
_reconnectTimer->setSingleShot(true);
connect(_reconnectTimer, &QTimer::timeout, [this]() {
reconnectToWebSocket();
});
_reconnectTimer->start();
return true;
}
void PushNotifications::onWebSocketSslErrors(const QList<QSslError> &errors)
{
qCWarning(lcPushNotifications) << "Received websocket ssl errors:" << errors;
_isReady = false;
emit authenticationFailed();
}
void PushNotifications::openWebSocket()
{
// Open websocket
const auto capabilities = _account->capabilities();
const auto webSocketUrl = capabilities.pushNotificationsWebSocketUrl();
if (!_webSocket) {
qCInfo(lcPushNotifications) << "Create websocket";
_webSocket = new QWebSocket(QString(), QWebSocketProtocol::VersionLatest, this);
}
if (_webSocket) {
connect(_webSocket, QOverload<QAbstractSocket::SocketError>::of(&QWebSocket::error), this, &PushNotifications::onWebSocketError, Qt::UniqueConnection);
connect(_webSocket, &QWebSocket::sslErrors, this, &PushNotifications::onWebSocketSslErrors, Qt::UniqueConnection);
connect(_webSocket, &QWebSocket::connected, this, &PushNotifications::onWebSocketConnected, Qt::UniqueConnection);
connect(_webSocket, &QWebSocket::disconnected, this, &PushNotifications::onWebSocketDisconnected, Qt::UniqueConnection);
qCInfo(lcPushNotifications) << "Open connection to websocket on:" << webSocketUrl;
_webSocket->open(webSocketUrl);
}
}
void PushNotifications::setReconnectTimerInterval(uint32_t interval)
{
_reconnectTimerInterval = interval;
}
bool PushNotifications::isReady() const
{
return _isReady;
}
void PushNotifications::handleAuthenticated()
{
qCInfo(lcPushNotifications) << "Authenticated successful on websocket";
_failedAuthenticationAttemptsCount = 0;
_isReady = true;
emit ready();
}
void PushNotifications::handleNotifyFile()
{
qCInfo(lcPushNotifications) << "Files push notification arrived";
emit filesChanged(_account);
}
void PushNotifications::handleInvalidCredentials()
{
qCInfo(lcPushNotifications) << "Invalid credentials submitted to websocket";
if (!tryReconnectToWebSocket()) {
_isReady = false;
emit authenticationFailed();
}
}
void PushNotifications::handleNotifyNotification()
{
qCInfo(lcPushNotifications) << "Push notification arrived";
emit notificationsChanged(_account);
}
void PushNotifications::handleNotifyActivity()
{
qCInfo(lcPushNotifications) << "Push activity arrived";
emit activitiesChanged(_account);
}
}

View File

@@ -0,0 +1,119 @@
/*
* Copyright (C) by Felix Weilbach <felix.weilbach@nextcloud.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program 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 General Public License
* for more details.
*/
#pragma once
#include <QWebSocket>
#include <QTimer>
#include "capabilities.h"
namespace OCC {
class Account;
class AbstractCredentials;
class OWNCLOUDSYNC_EXPORT PushNotifications : public QObject
{
Q_OBJECT
public:
explicit PushNotifications(Account *account, QObject *parent = nullptr);
~PushNotifications();
/**
* Setup push notifications
*
* This method needs to be called before push notifications can be used.
*/
void setup();
/**
* Set the interval for reconnection attempts
*/
void setReconnectTimerInterval(uint32_t interval);
/**
* Indicates if push notifications ready to use
*
* Ready to use means connected and authenticated.
*/
bool isReady() const;
signals:
/**
* Will be emitted after a successful connection and authentication
*/
void ready();
/**
* Will be emitted if files on the server changed
*/
void filesChanged(Account *account);
/**
* Will be emitted if activities have been changed on the server
*/
void activitiesChanged(Account *account);
/**
* Will be emitted if notifications have been changed on the server
*/
void notificationsChanged(Account *account);
/**
* Will be emitted if push notifications are unable to authenticate
*
* It's save to call #PushNotifications::setup() after this signal has been emitted.
*/
void authenticationFailed();
/**
* Will be emitted if push notifications are unable to connect or the connection timed out
*
* It's save to call #PushNotifications::setup() after this signal has been emitted.
*/
void connectionLost();
private slots:
void onWebSocketConnected();
void onWebSocketDisconnected();
void onWebSocketTextMessageReceived(const QString &message);
void onWebSocketError(QAbstractSocket::SocketError error);
void onWebSocketSslErrors(const QList<QSslError> &errors);
private:
void openWebSocket();
void reconnectToWebSocket();
void closeWebSocket();
void authenticateOnWebSocket();
bool tryReconnectToWebSocket();
void initReconnectTimer();
void handleAuthenticated();
void handleNotifyFile();
void handleInvalidCredentials();
void handleNotifyNotification();
void handleNotifyActivity();
Account *_account = nullptr;
QWebSocket *_webSocket = nullptr;
uint8_t _failedAuthenticationAttemptsCount = 0;
QTimer *_reconnectTimer = nullptr;
uint32_t _reconnectTimerInterval = 20 * 1000;
bool _isReady = false;
};
}

View File

@@ -50,6 +50,11 @@ QUrl imagePathToUrl(const QString &imagePath)
}
}
bool shouldPreferSvg()
{
return QByteArray(APPLICATION_ICON_SET).toUpper() == QByteArrayLiteral("SVG");
}
}
namespace OCC {
@@ -185,10 +190,11 @@ QIcon Theme::themeIcon(const QString &name, bool sysTray) const
return QPixmap(pixmapName);
};
const auto sizes = isBranded() ? QVector<int>{ 16, 22, 32, 48, 64, 128, 256, 512, 1024 }
: QVector<int>{ 16, 32, 64, 128, 256 };
const auto useSvg = shouldPreferSvg();
const auto sizes = useSvg ? QVector<int>{ 16, 32, 64, 128, 256 }
: QVector<int>{ 16, 22, 32, 48, 64, 128, 256, 512, 1024 };
for (int size : sizes) {
auto px = isBranded() ? loadPixmap(size) : createPixmapFromSvg(size);
auto px = useSvg ? createPixmapFromSvg(size) : loadPixmap(size);
if (px.isNull()) {
continue;
}
@@ -217,20 +223,25 @@ QIcon Theme::themeIcon(const QString &name, bool sysTray) const
QString Theme::themeImagePath(const QString &name, int size, bool sysTray) const
{
const auto flavor = (!isBranded() && sysTray) ? systrayIconFlavor(_mono) : QLatin1String("colored");
const auto useSvg = shouldPreferSvg();
// branded client may have several sizes of the same icon
const QString filePath = (isBranded() && size > 0)
? QString::fromLatin1(":/client/theme/%1/%2-%3").arg(flavor).arg(name).arg(size)
: QString::fromLatin1(":/client/theme/%1/%2").arg(flavor).arg(name);
const QString filePath = (useSvg || size <= 0)
? QString::fromLatin1(":/client/theme/%1/%2").arg(flavor).arg(name)
: QString::fromLatin1(":/client/theme/%1/%2-%3").arg(flavor).arg(name).arg(size);
const QString brandedImagePath = filePath + ".png";
// only return branded .png image path if it exists, or fall-back to non-branded .svg otherwise
if (isBranded() && QFile::exists(brandedImagePath)) {
return brandedImagePath;
const QString svgPath = filePath + ".svg";
if (useSvg) {
return svgPath;
}
return filePath + ".svg";
const QString pngPath = filePath + ".png";
// Use the SVG as fallback if a PNG is missing so that we get a chance to display something
if (QFile::exists(pngPath)) {
return pngPath;
} else {
return svgPath;
}
}
QIcon Theme::uiThemeIcon(const QString &iconName, bool uiHasDarkBg) const
@@ -528,7 +539,17 @@ QColor Theme::wizardHeaderBackgroundColor() const
QPixmap Theme::wizardHeaderLogo() const
{
#ifdef APPLICATION_WIZARD_USE_CUSTOM_LOGO
return QPixmap(hidpiFileName(":/client/theme/colored/wizard_logo.png"));
const auto useSvg = shouldPreferSvg();
const auto logoBasePath = QStringLiteral(":/client/theme/colored/wizard_logo");
if (useSvg) {
const auto maxHeight = 64;
const auto maxWidth = 2 * maxHeight;
const auto icon = QIcon(logoBasePath + ".svg");
const auto size = icon.actualSize(QSize(maxWidth, maxHeight));
return icon.pixmap(size);
} else {
return QPixmap(hidpiFileName(logoBasePath + ".png"));
}
#else
return applicationIcon().pixmap(64);
#endif

View File

@@ -54,6 +54,8 @@ nextcloud_add_test(UploadReset "syncenginetestutils.h")
nextcloud_add_test(AllFilesDeleted "syncenginetestutils.h")
nextcloud_add_test(Blacklist "syncenginetestutils.h")
nextcloud_add_test(FolderWatcher "${FolderWatcher_SRC}")
nextcloud_add_test(Capabilities "")
nextcloud_add_test(PushNotifications "pushnotificationstestutils.cpp")
if( UNIX AND NOT APPLE )
nextcloud_add_test(InotifyWatcher "${FolderWatcher_SRC}")
@@ -96,7 +98,7 @@ list(APPEND RemoteWipe_SRC ${RemoteWipe_SRC})
list(APPEND RemoteWipe_SRC stubremotewipe.cpp )
nextcloud_add_test(RemoteWipe "${RemoteWipe_SRC}")
nextcloud_add_test(OAuth "syncenginetestutils.h;../src/gui/creds/oauth.cpp")
nextcloud_add_test(OAuth "syncenginetestutils.h;../src/gui/creds/oauth.cpp;../src/gui/guiutility.cpp")
configure_file(test_journal.db "${PROJECT_BINARY_DIR}/bin/test_journal.db" COPYONLY)

View File

@@ -0,0 +1,137 @@
#include <QLoggingCategory>
#include <QSignalSpy>
#include <QTest>
#include "pushnotificationstestutils.h"
Q_LOGGING_CATEGORY(lcFakeWebSocketServer, "nextcloud.test.fakewebserver", QtInfoMsg)
FakeWebSocketServer::FakeWebSocketServer(quint16 port, QObject *parent)
: QObject(parent)
, _webSocketServer(new QWebSocketServer(QStringLiteral("Fake Server"), QWebSocketServer::NonSecureMode, this))
{
if (_webSocketServer->listen(QHostAddress::Any, port)) {
connect(_webSocketServer, &QWebSocketServer::newConnection, this, &FakeWebSocketServer::onNewConnection);
connect(_webSocketServer, &QWebSocketServer::closed, this, &FakeWebSocketServer::closed);
qCInfo(lcFakeWebSocketServer) << "Open fake websocket server on port:" << port;
return;
}
Q_UNREACHABLE();
}
FakeWebSocketServer::~FakeWebSocketServer()
{
close();
}
void FakeWebSocketServer::close()
{
if (_webSocketServer->isListening()) {
qCInfo(lcFakeWebSocketServer) << "Close fake websocket server";
_webSocketServer->close();
qDeleteAll(_clients.begin(), _clients.end());
}
}
void FakeWebSocketServer::processTextMessageInternal(const QString &message)
{
auto client = qobject_cast<QWebSocket *>(sender());
emit processTextMessage(client, message);
}
void FakeWebSocketServer::onNewConnection()
{
qCInfo(lcFakeWebSocketServer) << "New connection on fake websocket server";
auto socket = _webSocketServer->nextPendingConnection();
connect(socket, &QWebSocket::textMessageReceived, this, &FakeWebSocketServer::processTextMessageInternal);
connect(socket, &QWebSocket::disconnected, this, &FakeWebSocketServer::socketDisconnected);
_clients << socket;
}
void FakeWebSocketServer::socketDisconnected()
{
qCInfo(lcFakeWebSocketServer) << "Socket disconnected";
auto client = qobject_cast<QWebSocket *>(sender());
if (client) {
_clients.removeAll(client);
client->deleteLater();
}
}
OCC::AccountPtr FakeWebSocketServer::createAccount()
{
auto account = OCC::Account::create();
QStringList typeList;
typeList.append("files");
typeList.append("activities");
typeList.append("notifications");
QString websocketUrl("ws://localhost:12345");
QVariantMap endpointsMap;
endpointsMap["websocket"] = websocketUrl;
QVariantMap notifyPushMap;
notifyPushMap["type"] = typeList;
notifyPushMap["endpoints"] = endpointsMap;
QVariantMap capabilitiesMap;
capabilitiesMap["notify_push"] = notifyPushMap;
account->setCapabilities(capabilitiesMap);
return account;
}
CredentialsStub::CredentialsStub(const QString &user, const QString &password)
: _user(user)
, _password(password)
{
}
QString CredentialsStub::authType() const
{
return "";
}
QString CredentialsStub::user() const
{
return _user;
}
QString CredentialsStub::password() const
{
return _password;
}
QNetworkAccessManager *CredentialsStub::createQNAM() const
{
return nullptr;
}
bool CredentialsStub::ready() const
{
return false;
}
void CredentialsStub::fetchFromKeychain() { }
void CredentialsStub::askFromUser() { }
bool CredentialsStub::stillValid(QNetworkReply * /*reply*/)
{
return false;
}
void CredentialsStub::persist() { }
void CredentialsStub::invalidateToken() { }
void CredentialsStub::forgetSensitiveData() { }

View File

@@ -0,0 +1,73 @@
/*
* Copyright (C) by Felix Weilbach <felix.weilbach@nextcloud.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program 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 General Public License
* for more details.
*/
#pragma once
#include <functional>
#include <QWebSocketServer>
#include <QWebSocket>
#include "creds/abstractcredentials.h"
#include "account.h"
class FakeWebSocketServer : public QObject
{
Q_OBJECT
public:
explicit FakeWebSocketServer(quint16 port = 12345, QObject *parent = nullptr);
~FakeWebSocketServer();
void close();
static OCC::AccountPtr createAccount();
signals:
void closed();
void processTextMessage(QWebSocket *sender, const QString &message);
private slots:
void processTextMessageInternal(const QString &message);
void onNewConnection();
void socketDisconnected();
private:
QWebSocketServer *_webSocketServer;
QList<QWebSocket *> _clients;
};
class CredentialsStub : public OCC::AbstractCredentials
{
Q_OBJECT
public:
CredentialsStub(const QString &user, const QString &password);
virtual QString authType() const;
virtual QString user() const;
virtual QString password() const;
virtual QNetworkAccessManager *createQNAM() const;
virtual bool ready() const;
virtual void fetchFromKeychain();
virtual void askFromUser();
virtual bool stillValid(QNetworkReply *reply);
virtual void persist();
virtual void invalidateToken();
virtual void forgetSensitiveData();
private:
QString _user;
QString _password;
};

View File

@@ -859,6 +859,7 @@ public:
FakeCredentials(QNetworkAccessManager *qnam) : _qnam{qnam} { }
virtual QString authType() const { return "test"; }
virtual QString user() const { return "admin"; }
virtual QString password() const { return "password"; }
virtual QNetworkAccessManager *createQNAM() const { return _qnam; }
virtual bool ready() const { return true; }
virtual void fetchFromKeychain() { }

144
test/testcapabilities.cpp Normal file
View File

@@ -0,0 +1,144 @@
#include <QTest>
#include "capabilities.h"
class TestCapabilities : public QObject
{
Q_OBJECT
private slots:
void testPushNotificationsAvailable_pushNotificationsForActivitiesAvailable_returnTrue()
{
QStringList typeList;
typeList.append("activities");
QVariantMap notifyPushMap;
notifyPushMap["type"] = typeList;
QVariantMap capabilitiesMap;
capabilitiesMap["notify_push"] = notifyPushMap;
const auto &capabilities = OCC::Capabilities(capabilitiesMap);
const auto activitiesPushNotificationsAvailable = capabilities.availablePushNotifications().testFlag(OCC::PushNotificationType::Activities);
QCOMPARE(activitiesPushNotificationsAvailable, true);
}
void testPushNotificationsAvailable_pushNotificationsForActivitiesNotAvailable_returnFalse()
{
QStringList typeList;
typeList.append("noactivities");
QVariantMap notifyPushMap;
notifyPushMap["type"] = typeList;
QVariantMap capabilitiesMap;
capabilitiesMap["notify_push"] = notifyPushMap;
const auto &capabilities = OCC::Capabilities(capabilitiesMap);
const auto activitiesPushNotificationsAvailable = capabilities.availablePushNotifications().testFlag(OCC::PushNotificationType::Activities);
QCOMPARE(activitiesPushNotificationsAvailable, false);
}
void testPushNotificationsAvailable_pushNotificationsForFilesAvailable_returnTrue()
{
QStringList typeList;
typeList.append("files");
QVariantMap notifyPushMap;
notifyPushMap["type"] = typeList;
QVariantMap capabilitiesMap;
capabilitiesMap["notify_push"] = notifyPushMap;
const auto &capabilities = OCC::Capabilities(capabilitiesMap);
const auto filesPushNotificationsAvailable = capabilities.availablePushNotifications().testFlag(OCC::PushNotificationType::Files);
QCOMPARE(filesPushNotificationsAvailable, true);
}
void testPushNotificationsAvailable_pushNotificationsForFilesNotAvailable_returnFalse()
{
QStringList typeList;
typeList.append("nofiles");
QVariantMap notifyPushMap;
notifyPushMap["type"] = typeList;
QVariantMap capabilitiesMap;
capabilitiesMap["notify_push"] = notifyPushMap;
const auto &capabilities = OCC::Capabilities(capabilitiesMap);
const auto filesPushNotificationsAvailable = capabilities.availablePushNotifications().testFlag(OCC::PushNotificationType::Files);
QCOMPARE(filesPushNotificationsAvailable, false);
}
void testPushNotificationsAvailable_pushNotificationsForNotificationsAvailable_returnTrue()
{
QStringList typeList;
typeList.append("notifications");
QVariantMap notifyPushMap;
notifyPushMap["type"] = typeList;
QVariantMap capabilitiesMap;
capabilitiesMap["notify_push"] = notifyPushMap;
const auto &capabilities = OCC::Capabilities(capabilitiesMap);
const auto notificationsPushNotificationsAvailable = capabilities.availablePushNotifications().testFlag(OCC::PushNotificationType::Notifications);
QCOMPARE(notificationsPushNotificationsAvailable, true);
}
void testPushNotificationsAvailable_pushNotificationsForNotificationsNotAvailable_returnFalse()
{
QStringList typeList;
typeList.append("nonotifications");
QVariantMap notifyPushMap;
notifyPushMap["type"] = typeList;
QVariantMap capabilitiesMap;
capabilitiesMap["notify_push"] = notifyPushMap;
const auto &capabilities = OCC::Capabilities(capabilitiesMap);
const auto notificationsPushNotificationsAvailable = capabilities.availablePushNotifications().testFlag(OCC::PushNotificationType::Notifications);
QCOMPARE(notificationsPushNotificationsAvailable, false);
}
void testPushNotificationsAvailable_pushNotificationsNotAvailable_returnFalse()
{
const auto &capabilities = OCC::Capabilities(QVariantMap());
const auto activitiesPushNotificationsAvailable = capabilities.availablePushNotifications().testFlag(OCC::PushNotificationType::Activities);
const auto filesPushNotificationsAvailable = capabilities.availablePushNotifications().testFlag(OCC::PushNotificationType::Files);
const auto notificationsPushNotificationsAvailable = capabilities.availablePushNotifications().testFlag(OCC::PushNotificationType::Notifications);
QCOMPARE(activitiesPushNotificationsAvailable, false);
QCOMPARE(filesPushNotificationsAvailable, false);
QCOMPARE(notificationsPushNotificationsAvailable, false);
}
void testPushNotificationsWebSocketUrl_urlAvailable_returnUrl()
{
QString websocketUrl("testurl");
QVariantMap endpointsMap;
endpointsMap["websocket"] = websocketUrl;
QVariantMap notifyPushMap;
notifyPushMap["endpoints"] = endpointsMap;
QVariantMap capabilitiesMap;
capabilitiesMap["notify_push"] = notifyPushMap;
const auto &capabilities = OCC::Capabilities(capabilitiesMap);
QCOMPARE(capabilities.pushNotificationsWebSocketUrl(), websocketUrl);
}
};
QTEST_GUILESS_MAIN(TestCapabilities)
#include "testcapabilities.moc"

View File

@@ -0,0 +1,358 @@
#include <QTest>
#include <QVector>
#include <QWebSocketServer>
#include <QSignalSpy>
#include "pushnotifications.h"
#include "pushnotificationstestutils.h"
class TestPushNotifications : public QObject
{
Q_OBJECT
private slots:
void testSetup_correctCredentials_authenticateAndEmitReady()
{
FakeWebSocketServer fakeServer;
QSignalSpy processTextMessageSpy(&fakeServer, &FakeWebSocketServer::processTextMessage);
QVERIFY(processTextMessageSpy.isValid());
const QString user = "user";
const QString password = "password";
auto account = FakeWebSocketServer::createAccount();
auto credentials = new CredentialsStub(user, password);
account->setCredentials(credentials);
QSignalSpy readySpy(account->pushNotifications(), &OCC::PushNotifications::ready);
QVERIFY(readySpy.isValid());
// Wait for authentication
QVERIFY(processTextMessageSpy.wait());
// Right authentication data should be sent
QCOMPARE(processTextMessageSpy.count(), 2);
const auto socket = processTextMessageSpy.at(0).at(0).value<QWebSocket *>();
const auto userSent = processTextMessageSpy.at(0).at(1).toString();
const auto passwordSent = processTextMessageSpy.at(1).at(1).toString();
QCOMPARE(userSent, user);
QCOMPARE(passwordSent, password);
// Sent authenticated
socket->sendTextMessage("authenticated");
// Wait for ready signal
readySpy.wait();
QCOMPARE(readySpy.count(), 1);
QCOMPARE(account->pushNotifications()->isReady(), true);
}
void testOnWebSocketTextMessageReceived_notifyFileMessage_emitFilesChanged()
{
const QString user = "user";
const QString password = "password";
FakeWebSocketServer fakeServer;
QSignalSpy processTextMessageSpy(&fakeServer, &FakeWebSocketServer::processTextMessage);
QVERIFY(processTextMessageSpy.isValid());
auto account = FakeWebSocketServer::createAccount();
auto credentials = new CredentialsStub(user, password);
account->setCredentials(credentials);
QSignalSpy filesChangedSpy(account->pushNotifications(), &OCC::PushNotifications::filesChanged);
QVERIFY(filesChangedSpy.isValid());
// Wait for authentication and then send notify_file push notification
QVERIFY(processTextMessageSpy.wait());
QCOMPARE(processTextMessageSpy.count(), 2);
const auto socket = processTextMessageSpy.at(0).at(0).value<QWebSocket *>();
socket->sendTextMessage("notify_file");
// filesChanged signal should be emitted
QVERIFY(filesChangedSpy.wait());
QCOMPARE(filesChangedSpy.count(), 1);
auto accountFilesChanged = filesChangedSpy.at(0).at(0).value<OCC::Account *>();
QCOMPARE(accountFilesChanged, account.data());
}
void testOnWebSocketTextMessageReceived_notifyActivityMessage_emitNotification()
{
const QString user = "user";
const QString password = "password";
FakeWebSocketServer fakeServer;
QSignalSpy processTextMessageSpy(&fakeServer, &FakeWebSocketServer::processTextMessage);
QVERIFY(processTextMessageSpy.isValid());
auto account = FakeWebSocketServer::createAccount();
auto credentials = new CredentialsStub(user, password);
account->setCredentials(credentials);
QSignalSpy activitySpy(account->pushNotifications(), &OCC::PushNotifications::activitiesChanged);
QVERIFY(activitySpy.isValid());
// Wait for authentication and then send notify_file push notification
QVERIFY(processTextMessageSpy.wait());
QCOMPARE(processTextMessageSpy.count(), 2);
const auto socket = processTextMessageSpy.at(0).at(0).value<QWebSocket *>();
socket->sendTextMessage("notify_activity");
// notification signal should be emitted
QVERIFY(activitySpy.wait());
QCOMPARE(activitySpy.count(), 1);
auto accountFilesChanged = activitySpy.at(0).at(0).value<OCC::Account *>();
QCOMPARE(accountFilesChanged, account.data());
}
void testOnWebSocketTextMessageReceived_notifyNotificationMessage_emitNotification()
{
const QString user = "user";
const QString password = "password";
FakeWebSocketServer fakeServer;
QSignalSpy processTextMessageSpy(&fakeServer, &FakeWebSocketServer::processTextMessage);
QVERIFY(processTextMessageSpy.isValid());
auto account = FakeWebSocketServer::createAccount();
auto credentials = new CredentialsStub(user, password);
account->setCredentials(credentials);
QSignalSpy notificationSpy(account->pushNotifications(), &OCC::PushNotifications::notificationsChanged);
QVERIFY(notificationSpy.isValid());
// Wait for authentication and then send notify_file push notification
QVERIFY(processTextMessageSpy.wait());
QCOMPARE(processTextMessageSpy.count(), 2);
const auto socket = processTextMessageSpy.at(0).at(0).value<QWebSocket *>();
socket->sendTextMessage("notify_notification");
// notification signal should be emitted
QVERIFY(notificationSpy.wait());
QCOMPARE(notificationSpy.count(), 1);
auto accountFilesChanged = notificationSpy.at(0).at(0).value<OCC::Account *>();
QCOMPARE(accountFilesChanged, account.data());
}
void testOnWebSocketTextMessageReceived_invalidCredentialsMessage_reconnectWebSocket()
{
const QString user = "user";
const QString password = "password";
FakeWebSocketServer fakeServer;
QSignalSpy processTextMessageSpy(&fakeServer, &FakeWebSocketServer::processTextMessage);
QVERIFY(processTextMessageSpy.isValid());
auto account = FakeWebSocketServer::createAccount();
auto credentials = new CredentialsStub(user, password);
account->setCredentials(credentials);
// Need to set reconnect timer interval to zero for tests
account->pushNotifications()->setReconnectTimerInterval(0);
// Wait for authentication attempt and then sent invalid credentials
QVERIFY(processTextMessageSpy.wait());
QCOMPARE(processTextMessageSpy.count(), 2);
const auto socket = processTextMessageSpy.at(0).at(0).value<QWebSocket *>();
const auto firstPasswordSent = processTextMessageSpy.at(1).at(1).toString();
QCOMPARE(firstPasswordSent, password);
processTextMessageSpy.clear();
socket->sendTextMessage("err: Invalid credentials");
// Wait for a new authentication attempt
QVERIFY(processTextMessageSpy.wait());
QCOMPARE(processTextMessageSpy.count(), 2);
const auto secondPasswordSent = processTextMessageSpy.at(1).at(1).toString();
QCOMPARE(secondPasswordSent, password);
}
void testOnWebSocketError_connectionLost_emitConnectionLost()
{
const QString user = "user";
const QString password = "password";
FakeWebSocketServer fakeServer;
QSignalSpy processTextMessageSpy(&fakeServer, &FakeWebSocketServer::processTextMessage);
QVERIFY(processTextMessageSpy.isValid());
auto account = FakeWebSocketServer::createAccount();
auto credentials = new CredentialsStub(user, password);
account->setCredentials(credentials);
// Need to set reconnect timer interval to zero for tests
account->pushNotifications()->setReconnectTimerInterval(0);
QSignalSpy connectionLostSpy(account->pushNotifications(), &OCC::PushNotifications::connectionLost);
QVERIFY(connectionLostSpy.isValid());
// Wait for authentication and then sent a network error
processTextMessageSpy.wait();
QCOMPARE(processTextMessageSpy.count(), 2);
auto socket = processTextMessageSpy.at(0).at(0).value<QWebSocket *>();
socket->abort();
QVERIFY(connectionLostSpy.wait());
// Account handled connectionLost signal and deleted PushNotifications
QCOMPARE(account->pushNotifications(), nullptr);
}
void testSetup_maxConnectionAttemptsReached_deletePushNotifications()
{
const QString user = "user";
const QString password = "password";
FakeWebSocketServer fakeServer;
QSignalSpy processTextMessageSpy(&fakeServer, &FakeWebSocketServer::processTextMessage);
QVERIFY(processTextMessageSpy.isValid());
auto account = FakeWebSocketServer::createAccount();
auto credentials = new CredentialsStub(user, password);
account->setCredentials(credentials);
account->pushNotifications()->setReconnectTimerInterval(0);
QSignalSpy authenticationFailedSpy(account->pushNotifications(), &OCC::PushNotifications::authenticationFailed);
QVERIFY(authenticationFailedSpy.isValid());
// Let three authentication attempts fail
QVERIFY(processTextMessageSpy.wait());
QCOMPARE(processTextMessageSpy.count(), 2);
auto socket = processTextMessageSpy.at(0).at(0).value<QWebSocket *>();
socket->sendTextMessage("err: Invalid credentials");
QVERIFY(processTextMessageSpy.wait());
QCOMPARE(processTextMessageSpy.count(), 4);
socket = processTextMessageSpy.at(2).at(0).value<QWebSocket *>();
socket->sendTextMessage("err: Invalid credentials");
QVERIFY(processTextMessageSpy.wait());
QCOMPARE(processTextMessageSpy.count(), 6);
socket = processTextMessageSpy.at(4).at(0).value<QWebSocket *>();
socket->sendTextMessage("err: Invalid credentials");
// Now the authenticationFailed Signal should be emitted
QVERIFY(authenticationFailedSpy.wait());
QCOMPARE(authenticationFailedSpy.count(), 1);
// Account deleted the push notifications
QCOMPARE(account->pushNotifications(), nullptr);
}
void testOnWebSocketSslError_sslError_deletePushNotifications()
{
const QString user = "user";
const QString password = "password";
FakeWebSocketServer fakeServer;
QSignalSpy processTextMessageSpy(&fakeServer, &FakeWebSocketServer::processTextMessage);
QVERIFY(processTextMessageSpy.isValid());
auto account = FakeWebSocketServer::createAccount();
auto credentials = new CredentialsStub(user, password);
account->setCredentials(credentials);
processTextMessageSpy.wait();
// FIXME: This a little bit ugly but I had no better idea how to trigger a error on the websocket client.
// The websocket that is retrived through the server is not connected to the ssl error signal.
auto pushNotificationsWebSocketChildren = account->pushNotifications()->findChildren<QWebSocket *>();
QVERIFY(pushNotificationsWebSocketChildren.size() == 1);
emit pushNotificationsWebSocketChildren[0]->sslErrors(QList<QSslError>());
// Account handled connectionLost signal and deleted PushNotifications
QCOMPARE(account->pushNotifications(), nullptr);
}
void testAccountSetCredentials_correctCredentials_emitPushNotificationsReady()
{
FakeWebSocketServer fakeServer;
auto account = FakeWebSocketServer::createAccount();
QSignalSpy processTextMessageSpy(&fakeServer, &FakeWebSocketServer::processTextMessage);
QVERIFY(processTextMessageSpy.isValid());
const QString user = "user";
const QString password = "password";
auto credentials = new CredentialsStub(user, password);
account->setCredentials(credentials);
QSignalSpy pushNotificationsReady(account.data(), &OCC::Account::pushNotificationsReady);
QVERIFY(pushNotificationsReady.isValid());
// Wait for authentication
QVERIFY(processTextMessageSpy.wait());
auto socket = processTextMessageSpy.at(0).at(0).value<QWebSocket *>();
// Don't care about which message was sent
socket->sendTextMessage("authenticated");
// Wait for push notifactions ready signal
QVERIFY(pushNotificationsReady.wait());
auto accountSent = pushNotificationsReady.at(0).at(0).value<OCC::Account *>();
QCOMPARE(accountSent, account.data());
}
void testAccount_web_socket_connectionLost_emitNotificationsDisabled()
{
FakeWebSocketServer fakeServer;
auto account = FakeWebSocketServer::createAccount();
QSignalSpy processTextMessageSpy(&fakeServer, &FakeWebSocketServer::processTextMessage);
QVERIFY(processTextMessageSpy.isValid());
const QString user = "user";
const QString password = "password";
auto credentials = new CredentialsStub(user, password);
account->setCredentials(credentials);
// Need to set reconnect timer interval to zero for tests
account->pushNotifications()->setReconnectTimerInterval(0);
QSignalSpy connectionLostSpy(account->pushNotifications(), &OCC::PushNotifications::connectionLost);
QVERIFY(connectionLostSpy.isValid());
QSignalSpy pushNotificationsDisabledSpy(account.data(), &OCC::Account::pushNotificationsDisabled);
QVERIFY(pushNotificationsDisabledSpy.isValid());
// Wait for authentication and then sent a network error
processTextMessageSpy.wait();
QCOMPARE(processTextMessageSpy.count(), 2);
auto socket = processTextMessageSpy.at(0).at(0).value<QWebSocket *>();
socket->abort();
QVERIFY(pushNotificationsDisabledSpy.wait());
QCOMPARE(pushNotificationsDisabledSpy.count(), 1);
QCOMPARE(connectionLostSpy.count(), 1);
auto accountSent = pushNotificationsDisabledSpy.at(0).at(0).value<OCC::Account *>();
QCOMPARE(accountSent, account.data());
}
void testAccount_web_socket_authenticationFailed_emitNotificationsDisabled()
{
FakeWebSocketServer fakeServer;
auto account = FakeWebSocketServer::createAccount();
QSignalSpy processTextMessageSpy(&fakeServer, &FakeWebSocketServer::processTextMessage);
QVERIFY(processTextMessageSpy.isValid());
const QString user = "user";
const QString password = "password";
auto credentials = new CredentialsStub(user, password);
account->setCredentials(credentials);
account->pushNotifications()->setReconnectTimerInterval(0);
QSignalSpy authenticationFailedSpy(account->pushNotifications(), &OCC::PushNotifications::authenticationFailed);
QVERIFY(authenticationFailedSpy.isValid());
QSignalSpy pushNotificationsDisabledSpy(account.data(), &OCC::Account::pushNotificationsDisabled);
QVERIFY(pushNotificationsDisabledSpy.isValid());
// Let three authentication attempts fail
QVERIFY(processTextMessageSpy.wait());
QCOMPARE(processTextMessageSpy.count(), 2);
auto socket = processTextMessageSpy.at(0).at(0).value<QWebSocket *>();
socket->sendTextMessage("err: Invalid credentials");
QVERIFY(processTextMessageSpy.wait());
QCOMPARE(processTextMessageSpy.count(), 4);
socket = processTextMessageSpy.at(2).at(0).value<QWebSocket *>();
socket->sendTextMessage("err: Invalid credentials");
QVERIFY(processTextMessageSpy.wait());
QCOMPARE(processTextMessageSpy.count(), 6);
socket = processTextMessageSpy.at(4).at(0).value<QWebSocket *>();
socket->sendTextMessage("err: Invalid credentials");
// Now the authenticationFailed and pushNotificationsDisabled Signals should be emitted
QVERIFY(pushNotificationsDisabledSpy.wait());
QCOMPARE(pushNotificationsDisabledSpy.count(), 1);
QCOMPARE(authenticationFailedSpy.count(), 1);
auto accountSent = pushNotificationsDisabledSpy.at(0).at(0).value<OCC::Account *>();
QCOMPARE(accountSent, account.data());
}
};
QTEST_GUILESS_MAIN(TestPushNotifications)
#include "testpushnotifications.moc"

View File

@@ -27,6 +27,7 @@
<file>theme/colored/state-sync-256.png</file>
<file>theme/colored/wizard_logo.png</file>
<file>theme/colored/wizard_logo@2x.png</file>
<file>theme/colored/wizard_logo.svg</file>
<file>theme/white/state-error-32.png</file>
<file>theme/white/state-error-64.png</file>
<file>theme/white/state-error-128.png</file>

Some files were not shown because too many files have changed in this diff Show More