Browse Source

v.0.4

master
LubuWest 5 months ago
parent
commit
63dfb9b197
70 changed files with 2818 additions and 1045 deletions
  1. 18
    15
      CHANGELOG.md
  2. 2
    1
      README.md
  3. 37
    1
      source-android/android/AndroidManifest.xml
  4. 8
    1
      source-android/android/build.gradle
  5. 0
    8
      source-android/android/src/FriendiqaActivity.java
  6. 96
    0
      source-android/android/src/FriendiqaNotifierService.java
  7. 35
    0
      source-android/android/src/FriendiqaService.java
  8. 40
    0
      source-android/android/src/FriendiqaStopService.java
  9. 37
    0
      source-android/androidnative.pri/java/src/androidnative/AndroidNativeActivity.java
  10. 23
    0
      source-android/androidnative.pri/java/src/androidnative/AndroidNativeService.java
  11. 63
    2
      source-android/androidnative.pri/java/src/androidnative/Util.java
  12. 2
    0
      source-android/application.qrc
  13. 59
    0
      source-android/common/alarm.h
  14. 82
    0
      source-android/common/alarmandroid.cpp
  15. 23
    1
      source-android/common/friendiqa.cpp
  16. 399
    0
      source-android/common/updatenews.cpp
  17. 92
    0
      source-android/common/updatenews.h
  18. 1
    1
      source-android/common/xhr.cpp
  19. 1
    1
      source-android/common/xhr.h
  20. 9
    4
      source-android/friendiqa.pro
  21. 14
    0
      source-android/js/helper.js
  22. 1
    1
      source-android/js/news.js
  23. 15
    0
      source-android/js/newsworker.js
  24. 7
    7
      source-android/js/service.js
  25. 45
    0
      source-android/js/yplayer.html
  26. 143
    127
      source-android/qml/configqml/ConfigTab.qml
  27. 1
    1
      source-android/qml/configqml/InfoBox.qml
  28. 1
    0
      source-android/qml/configqml/OSSettingsAndroid.qml
  29. 1
    0
      source-android/qml/configqml/OSSettingsLinux.qml
  30. 4
    2
      source-android/qml/friendiqa.qml
  31. 4
    0
      source-android/qml/genericqml/IntentReceiver.qml
  32. 19
    4
      source-android/qml/newsqml/NewsLink.qml
  33. 29
    0
      source-android/qml/newsqml/NewsTab.qml
  34. 100
    0
      source-android/qml/newsqml/NewsYplayer.qml
  35. 4
    12
      source-android/qml/newsqml/Newsitem.qml
  36. BIN
      source-android/translations/friendiqa-de.qm
  37. 103
    78
      source-android/translations/friendiqa-de.ts
  38. BIN
      source-android/translations/friendiqa-es.qm
  39. 103
    78
      source-android/translations/friendiqa-es.ts
  40. BIN
      source-android/translations/friendiqa-it.qm
  41. 103
    78
      source-android/translations/friendiqa-it.ts
  42. 60
    0
      source-linux/common/alarm.h
  43. 76
    0
      source-linux/common/alarmandroid.cpp
  44. 4
    4
      source-linux/common/friendiqa.cpp
  45. 196
    178
      source-linux/common/updatenews.cpp
  46. 38
    27
      source-linux/common/updatenews.h
  47. 2
    1
      source-linux/common/xhr.cpp
  48. 1
    1
      source-linux/common/xhr.h
  49. 4
    5
      source-linux/friendiqa.pro
  50. 14
    0
      source-linux/js/helper.js
  51. 1
    1
      source-linux/js/news.js
  52. 15
    0
      source-linux/js/newsworker.js
  53. 7
    7
      source-linux/js/service.js
  54. 45
    0
      source-linux/js/yplayer.html
  55. 145
    128
      source-linux/qml/configqml/ConfigTab.qml
  56. 1
    1
      source-linux/qml/configqml/InfoBox.qml
  57. 1
    0
      source-linux/qml/configqml/OSSettingsAndroid.qml
  58. 1
    0
      source-linux/qml/configqml/OSSettingsLinux.qml
  59. 16
    14
      source-linux/qml/friendiqa.qml
  60. 4
    0
      source-linux/qml/genericqml/IntentReceiver.qml
  61. 19
    4
      source-linux/qml/newsqml/NewsLink.qml
  62. 29
    0
      source-linux/qml/newsqml/NewsTab.qml
  63. 100
    0
      source-linux/qml/newsqml/NewsYplayer.qml
  64. 6
    17
      source-linux/qml/newsqml/Newsitem.qml
  65. BIN
      source-linux/translations/friendiqa-de.qm
  66. 103
    78
      source-linux/translations/friendiqa-de.ts
  67. BIN
      source-linux/translations/friendiqa-es.qm
  68. 103
    78
      source-linux/translations/friendiqa-es.ts
  69. BIN
      source-linux/translations/friendiqa-it.qm
  70. 103
    78
      source-linux/translations/friendiqa-it.ts

+ 18
- 15
CHANGELOG.md View File

@@ -84,23 +84,26 @@
84 84
 
85 85
 ## v0.3.2 ##
86 86
 *  For news containing url ending with mp3, mp4, avi, webm, ogg: media can be played in app
87
-*   Pictures can be renamed or moved to another album
88
-*   Bugfix: random crashes for conversations
89
-*   Bugfix: attach image to message works again
90
-*   Bugfix: check for nickname on Server has been removed due to API change
87
+*  Pictures can be renamed or moved to another album
88
+*  Bugfix: random crashes for conversations
89
+*  Bugfix: attach image to message works again
90
+*  Bugfix: check for nickname on Server has been removed due to API change
91 91
 
92 92
 
93 93
 ## v0.3.3 ##
94
-* Update for OpenSSL and At
95
-* Experimental support for Peertube (links are expanded to video widget)
96
-* Some Unicode emojis
97
-* Redesign of contact details (click on contact opens in new stack and shows last news)
98
-
94
+*  Update for OpenSSL and At
95
+*  Experimental support for Peertube (links are expanded to video widget)
96
+*  Some Unicode emojis
97
+*  Redesign of contact details (click on contact opens in new stack and shows last news)
99 98
 
100 99
 ## v0.3.4 ##
101
-* Direct message creation from profile page works again
102
-* Profile image upload works again
103
-* Viewing private album pictures of contacts works again
104
-* On first start servername from https://dir.friendica.social/servers/surprise selected
105
-* Register button opens webview of registration page on server
106
-
100
+*  Direct message creation from profile page works again
101
+*  Profile image upload works again
102
+*  Viewing private album pictures of contacts works again
103
+*  On first start servername from https://dir.friendica.social/servers/surprise selected
104
+*  Register button opens webview of registration page on server
105
+
106
+## v0.4 ##
107
+*  Background sync for friends timeline (interval on config page must be > 0) for Android > 5
108
+*  Replies timeline
109
+*  Bugfix: App asks for storage permission on first start

+ 2
- 1
README.md View File

@@ -18,7 +18,8 @@ QML based client for the Friendica Social Network.
18 18
 
19 19
 # News #
20 20
 Currently supported:
21
-*  Shows Posts from friends, selected group, favorited messages, public timeline, Direct Messages and notifications
21
+*  Shows Posts from friends, selected group, replies, favorited messages, public timeline, Direct Messages and notifications
22
+*  Background sync with configurable interval of 15 min to 2h for active contact for friends timeline (Android 5 required)
22 23
 *  Search button for news
23 24
 *  Click on hashtag in newsitem starts search for news with that word
24 25
 *  Click on image shows image fullscreen

+ 37
- 1
source-android/android/AndroidManifest.xml View File

@@ -1,5 +1,5 @@
1 1
 <?xml version="1.0"?>
2
-<manifest package="org.qtproject.friendiqa" xmlns:android="http://schemas.android.com/apk/res/android" android:versionName="0.3.4" android:versionCode="11" android:installLocation="auto">
2
+<manifest package="org.qtproject.friendiqa" xmlns:android="http://schemas.android.com/apk/res/android" android:versionName="0.4" android:versionCode="12" android:installLocation="auto">
3 3
     <application android:hardwareAccelerated="true" android:vmSafeMode="true" android:name="org.qtproject.qt5.android.bindings.QtApplication" android:label="Friendiqa" android:icon="@drawable/friendiqa" android:logo="@drawable/friendiqa" android:theme="@android:style/Theme.Holo.Light">
4 4
         <activity android:configChanges="orientation|uiMode|screenLayout|screenSize|smallestScreenSize|layoutDirection|locale|fontScale|keyboard|keyboardHidden|navigation" android:name="androidnative.friendiqa.FriendiqaActivity" android:label="Friendiqa" android:screenOrientation="unspecified" android:launchMode="singleInstance" android:taskAffinity="">
5 5
             <intent-filter>
@@ -49,6 +49,42 @@
49 49
             <meta-data android:name="android.app.background_running" android:value="false"/>
50 50
             <!-- Background running -->
51 51
         </activity>
52
+
53
+        <service android:name="androidnative.friendiqa.FriendiqaService" android:permission="android.permission.BIND_JOB_SERVICE">
54
+            <meta-data android:name="android.app.background_running" android:value="true"/>
55
+        </service>
56
+        <service android:process=":qt" android:name="androidnative.AndroidNativeService">
57
+            <meta-data android:name="android.app.background_running" android:value="true"/>
58
+            <meta-data android:name="android.app.arguments" android:value="-service"/>
59
+            <meta-data android:name="android.app.lib_name" android:value="friendiqa"/>
60
+            <meta-data android:name="android.app.qt_sources_resource_id" android:resource="@array/qt_sources"/>
61
+            <meta-data android:name="android.app.repository" android:value="default"/>
62
+            <meta-data android:name="android.app.qt_libs_resource_id" android:resource="@array/qt_libs"/>
63
+            <meta-data android:name="android.app.bundled_libs_resource_id" android:resource="@array/bundled_libs"/>
64
+            <!-- Deploy Qt libs as part of package -->
65
+            <meta-data android:name="android.app.bundle_local_qt_libs" android:value="-- %%BUNDLE_LOCAL_QT_LIBS%% --"/>
66
+            <meta-data android:name="android.app.bundled_in_lib_resource_id" android:resource="@array/bundled_in_lib"/>
67
+            <meta-data android:name="android.app.bundled_in_assets_resource_id" android:resource="@array/bundled_in_assets"/>
68
+            <!-- Run with local libs -->
69
+            <meta-data android:name="android.app.use_local_qt_libs" android:value="-- %%USE_LOCAL_QT_LIBS%% --"/>
70
+            <meta-data android:name="android.app.libs_prefix" android:value="/data/local/tmp/qt/"/>
71
+            <meta-data android:name="android.app.load_local_libs" android:value="-- %%INSERT_LOCAL_LIBS%% --"/>
72
+            <meta-data android:name="android.app.load_local_jars" android:value="-- %%INSERT_LOCAL_JARS%% --"/>
73
+            <meta-data android:name="android.app.static_init_classes" android:value="-- %%INSERT_INIT_CLASSES%% --"/>
74
+            <!--  Messages maps -->
75
+            <meta-data android:value="@string/ministro_not_found_msg" android:name="android.app.ministro_not_found_msg"/>
76
+            <meta-data android:value="@string/ministro_needed_msg" android:name="android.app.ministro_needed_msg"/>
77
+            <meta-data android:value="@string/fatal_error_msg" android:name="android.app.fatal_error_msg"/>
78
+            <!--  Messages maps -->
79
+            <meta-data android:name="android.app.splash_screen_drawable" android:resource="@drawable/splash"/>
80
+        </service>
81
+        
82
+        <service android:process=":qt" android:name="androidnative.friendiqa.FriendiqaStopService" android:permission="android.permission.BIND_JOB_SERVICE"
83
+        android:exported="true">
84
+            <meta-data android:name="android.app.background_running" android:value="true"/>
85
+        </service>
86
+        
87
+        
52 88
     </application>
53 89
     <uses-sdk android:minSdkVersion="18" android:targetSdkVersion="26"/>
54 90
     <supports-screens android:largeScreens="true" android:normalScreens="true" android:anyDensity="true" android:smallScreens="true"/>

+ 8
- 1
source-android/android/build.gradle View File

@@ -20,6 +20,13 @@ dependencies {
20 20
     compile fileTree(dir: 'libs', include: ['*.jar'])
21 21
 }
22 22
 
23
+//apply plugin: 'android-library'
24
+
25
+dependencies {
26
+    compile 'com.android.support:support-v4:25.3.1'
27
+}
28
+
29
+
23 30
 android {
24 31
     /*******************************************************
25 32
      * The following variables:
@@ -56,4 +63,4 @@ android {
56 63
     }
57 64
 }
58 65
     apply from: "androidnative.gradle"
59
-    setAndroidNativePath("/../androidnative.pri");
66
+    setAndroidNativePath("/../androidnative.pri");

+ 0
- 8
source-android/android/src/FriendiqaActivity.java View File

@@ -2,10 +2,6 @@ package androidnative.friendiqa;
2 2
 
3 3
 import androidnative.AndroidNativeActivity;
4 4
 
5
-
6
-
7
-
8
-
9 5
 public class FriendiqaActivity extends AndroidNativeActivity {
10 6
     public FriendiqaActivity() {
11 7
         super();
@@ -13,8 +9,4 @@ public class FriendiqaActivity extends AndroidNativeActivity {
13 9
         QT_ANDROID_THEMES = new String[] {""};
14 10
         QT_ANDROID_DEFAULT_THEME = "";
15 11
     }
16
-
17
-
18
-
19
-
20 12
 }

+ 96
- 0
source-android/android/src/FriendiqaNotifierService.java View File

@@ -0,0 +1,96 @@
1
+package androidnative.friendiqa;
2
+import androidnative.SystemDispatcher;
3
+import android.app.Notification;
4
+import android.app.NotificationManager;
5
+import android.util.Log;
6
+import android.os.Handler;
7
+import android.app.Activity;
8
+import android.view.View;
9
+import android.content.Context;
10
+import java.util.Map;
11
+import org.qtproject.qt5.android.QtNative;
12
+
13
+public class FriendiqaNotifierService {
14
+
15
+    static {
16
+
17
+        SystemDispatcher.addListener(new SystemDispatcher.Listener() {
18
+
19
+            NotificationManager m_notificationManager;
20
+            Notification.Builder m_builder;
21
+
22
+            private void notificationManagerNotify(Map data) {
23
+
24
+                final Activity activity = QtNative.activity();
25
+                final Map messageData = data;
26
+
27
+                Runnable runnable = new Runnable () {
28
+                    public void run() {
29
+                        try {
30
+                            String title = (String) messageData.get("title");
31
+
32
+                            String message = (String) messageData.get("message");
33
+
34
+                            if (m_notificationManager == null) {
35
+                                m_notificationManager = (NotificationManager) activity.getSystemService(Context.NOTIFICATION_SERVICE);
36
+                                m_builder = new Notification.Builder(activity);
37
+
38
+                                // Small Icon is a must to make notification works.
39
+                                // And that is why you need to inherit QtActivity
40
+                                //m_builder.setSmallIcon(drawable.icon);
41
+                            }
42
+
43
+                            m_builder.setContentTitle(title);
44
+                            m_builder.setContentText(message);
45
+                            m_notificationManager.notify(1, m_builder.build());
46
+
47
+                            // Test function. Remove it later.
48
+                            SystemDispatcher.dispatch("Notifier.notifyFinished");
49
+                        } catch (Exception e) {
50
+                            Log.d("",e.getMessage());
51
+                        }
52
+
53
+                    };
54
+                };
55
+                activity.runOnUiThread(runnable);
56
+            }
57
+
58
+            private void hapticFeedbackPerform(Map data) {
59
+
60
+                final Activity activity = QtNative.activity();
61
+                final Map messageData = data;
62
+                Runnable runnable = new Runnable () {
63
+                    public void run() {
64
+                        int feedbackConstant = (Integer) messageData.get("feedbackConstant");
65
+                        int flags = (Integer) messageData.get("flags");
66
+
67
+                        Log.d("",String.format("hapticFeedbackPerform(%d,%d)",feedbackConstant,flags));
68
+
69
+                        View rootView = activity.getWindow().getDecorView().getRootView();
70
+                        rootView.performHapticFeedback(feedbackConstant, flags);
71
+
72
+                        // Test function. Remove it later.
73
+                        SystemDispatcher.dispatch("hapticFeedbackPerformFinished");
74
+                    };
75
+                };
76
+                activity.runOnUiThread(runnable);
77
+            }
78
+
79
+            public void onDispatched(String name , Map data) {
80
+
81
+                if (name.equals("Notifier.notify")) {
82
+                    notificationManagerNotify(data);
83
+                    return;
84
+                } else if (name.equals("hapticFeedbackPerform")) {
85
+                    hapticFeedbackPerform(data);
86
+                    return;
87
+                }
88
+
89
+                return;
90
+            }
91
+        });
92
+
93
+    }
94
+
95
+}
96
+

+ 35
- 0
source-android/android/src/FriendiqaService.java View File

@@ -0,0 +1,35 @@
1
+package androidnative.friendiqa;
2
+import android.content.Context;
3
+import android.content.Intent;
4
+import android.util.Log;
5
+import android.app.job.JobService;
6
+import android.app.job.JobParameters;
7
+import androidnative.AndroidNativeService;
8
+import org.qtproject.qt5.android.bindings.QtService;
9
+import org.qtproject.qt5.android.QtNative;
10
+//import androidnative.friendiqa.FriendiqaQtService;
11
+
12
+public class FriendiqaService extends JobService{
13
+	private static String TAG = "AndroidNative";
14
+	//Log.e(TAG,"Service");
15
+
16
+
17
+    @Override
18
+    public boolean onStartJob(JobParameters params) {
19
+        //Log.d(TAG,"Friendiqa JobService");
20
+	Context context = this.getApplicationContext();
21
+        AndroidNativeService fs = new AndroidNativeService();
22
+	fs.startQtService(context);
23
+	jobFinished(params,false);
24
+	//Intent serviceIntent = new Intent(this, AndroidNativeService.class);
25
+        //startService(serviceIntent);
26
+        return false;
27
+    }
28
+
29
+    @Override
30
+    public boolean onStopJob(JobParameters params) {
31
+        // whether or not you would like JobScheduler to automatically retry your failed job.
32
+        return false;
33
+    }
34
+}
35
+

+ 40
- 0
source-android/android/src/FriendiqaStopService.java View File

@@ -0,0 +1,40 @@
1
+package androidnative.friendiqa;
2
+import android.content.Context;
3
+import android.content.Intent;
4
+import android.util.Log;
5
+import android.app.job.JobService;
6
+import android.app.job.JobParameters;
7
+import androidnative.AndroidNativeService;
8
+import org.qtproject.qt5.android.bindings.QtService;
9
+import org.qtproject.qt5.android.QtNative;
10
+//import androidnative.friendiqa.FriendiqaQtService;
11
+
12
+public class FriendiqaStopService extends JobService{
13
+	private static String TAG = "AndroidNative";
14
+	//Log.e(TAG,"Service");
15
+
16
+
17
+    @Override
18
+    public boolean onStartJob(JobParameters params) {
19
+        //Log.d(TAG,"Friendiqa JobServiceStop");
20
+	Context context = this.getApplicationContext();
21
+        AndroidNativeService fs = new AndroidNativeService();
22
+	fs.stopQtService(context);
23
+	jobFinished(params,false);
24
+	//Intent serviceIntent = new Intent(this, AndroidNativeService.class);
25
+        //startService(serviceIntent);
26
+        return false;
27
+    }
28
+
29
+    @Override
30
+    public boolean onStopJob(JobParameters params) {
31
+        // whether or not you would like JobScheduler to automatically retry your failed job.
32
+        return true;
33
+    }
34
+    @Override
35
+    public boolean onUnbind(Intent intent) {
36
+        stopSelf();
37
+        return super.onUnbind(intent);
38
+    }
39
+
40
+}

+ 37
- 0
source-android/androidnative.pri/java/src/androidnative/AndroidNativeActivity.java View File

@@ -4,6 +4,11 @@ import android.util.Log;
4 4
 import android.app.Activity;
5 5
 import android.os.*;
6 6
 import java.util.Map;
7
+import android.content.pm.PackageManager;
8
+import android.content.Context;
9
+import android.Manifest.permission;
10
+import android.support.v4.app.ActivityCompat;
11
+import android.support.v4.content.ContextCompat;
7 12
 
8 13
 /** An alternative Activity class for Qt applicaiton.
9 14
 
@@ -11,6 +16,8 @@ import java.util.Map;
11 16
  */
12 17
 
13 18
 public class AndroidNativeActivity extends org.qtproject.qt5.android.bindings.QtActivity {
19
+	public static final int MY_PERMISSIONS_REQUEST_WRITE_STORAGE = 0x245285a8;
20
+
14 21
 
15 22
     @Override
16 23
     protected void onActivityResult(int requestCode, int resultCode, Intent data) {
@@ -21,6 +28,17 @@ public class AndroidNativeActivity extends org.qtproject.qt5.android.bindings.Qt
21 28
 
22 29
     protected void onResume() {
23 30
         super.onResume();
31
+	if (ContextCompat.checkSelfPermission(this,android.Manifest.permission.WRITE_EXTERNAL_STORAGE)!= PackageManager.PERMISSION_GRANTED) {
32
+
33
+    	// Permission is not granted
34
+
35
+        	ActivityCompat.requestPermissions(this,new String[]{android.Manifest.permission.WRITE_EXTERNAL_STORAGE},MY_PERMISSIONS_REQUEST_WRITE_STORAGE);
36
+
37
+        	// MY_PERMISSIONS_REQUEST_READ_CONTACTS is an
38
+        	// app-defined int constant. The callback method gets the
39
+        	// result of the request.
40
+	} else {
41
+
24 42
 	System.loadLibrary("friendiqa");
25 43
         if((getIntent().getFlags() == (Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY)) || (getIntent().getFlags() == Intent.FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY) || (getIntent().getFlags() == Intent.FLAG_ACTIVITY_NEW_TASK) || (getIntent().getFlags() == Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) || (getIntent().getFlags() == (Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED))) {
26 44
             SystemDispatcher.onActivityResume();
@@ -48,6 +66,25 @@ public class AndroidNativeActivity extends org.qtproject.qt5.android.bindings.Qt
48 66
                 SystemDispatcher.onActivityResume();
49 67
 	}}
50 68
     }
69
+    }
70
+
71
+
72
+
73
+
74
+	@Override public void onRequestPermissionsResult(int requestCode,String permissions[], int[] grantResults) {
75
+    		switch (requestCode) {
76
+        		case MY_PERMISSIONS_REQUEST_WRITE_STORAGE: {
77
+            		// If request is cancelled, the result arrays are empty.
78
+            		if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
79
+				SystemDispatcher.onActivityResume();
80
+            		} else {
81
+                        }
82
+               return;
83
+        }
84
+    }
85
+}
86
+
87
+
51 88
 
52 89
     protected void onNewIntent(Intent data) {  
53 90
       System.loadLibrary("friendiqa");  

+ 23
- 0
source-android/androidnative.pri/java/src/androidnative/AndroidNativeService.java View File

@@ -0,0 +1,23 @@
1
+package androidnative;
2
+import android.content.Context;
3
+import android.content.Intent;
4
+import android.util.Log;
5
+import org.qtproject.qt5.android.bindings.QtService;
6
+   
7
+public class AndroidNativeService extends QtService
8
+    {
9
+        private static String TAG = "AndroidNative";
10
+  
11
+        public void startQtService(Context ctx) {
12
+	   Log.d(TAG,"Friendiqa QtService");	
13
+           ctx.startService(new Intent(ctx, AndroidNativeService.class));
14
+        }
15
+        
16
+	public static void stopQtService(Context ctx) {
17
+  	   Log.d(TAG,"Friendiqa QtServiceStop");
18
+
19
+           ctx.stopService(new Intent(ctx, AndroidNativeService.class));
20
+        } 
21
+      
22
+       
23
+    }

+ 63
- 2
source-android/androidnative.pri/java/src/androidnative/Util.java View File

@@ -6,9 +6,15 @@ import android.util.Log;
6 6
 import android.view.View;
7 7
 import android.view.Window;
8 8
 import android.view.WindowManager;
9
-
9
+import android.content.Context;
10
+import android.content.ComponentName;
11
+import android.app.job.JobScheduler;
12
+import android.app.job.JobInfo;
10 13
 import org.qtproject.qt5.android.QtNative;
11
-
14
+import androidnative.friendiqa.FriendiqaService;
15
+import androidnative.friendiqa.FriendiqaStopService;
16
+import androidnative.AndroidNativeService;
17
+import android.content.Intent;
12 18
 import java.util.Map;
13 19
 
14 20
 public class Util {
@@ -17,6 +23,7 @@ public class Util {
17 23
 
18 24
     public static final String SET_TRANSLUCENT_STATUS_BAR = "androidnative.Util.setTranslucentStatusBar";
19 25
     public static final String SET_FULL_SCREEN = "androidnative.Util.setFullScreen";
26
+    public static final String SET_SCHEDULE = "androidnative.Util.setSchedule";
20 27
 
21 28
 
22 29
     static {
@@ -26,6 +33,8 @@ public class Util {
26 33
                     setTranslucentStatusBar(message);
27 34
                 } else if (type.equals(SET_FULL_SCREEN)) {
28 35
                     setFullScreen(message);
36
+                } else if (type.equals(SET_SCHEDULE)) {
37
+                    setSchedule(message);
29 38
                 }
30 39
             }
31 40
         });
@@ -62,6 +71,10 @@ public class Util {
62 71
             return;
63 72
         }
64 73
 
74
+        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
75
+            return;
76
+        }
77
+
65 78
         final Boolean value = (Boolean) message.get("value");
66 79
         final Activity activity = QtNative.activity();
67 80
 
@@ -84,4 +97,52 @@ public class Util {
84 97
         activity.runOnUiThread(runnable);
85 98
 
86 99
     }
100
+
101
+    static void setSchedule(Map message) {
102
+        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
103
+            return;
104
+        }
105
+        Log.d(TAG,"Friendiqa schedule Androidnative service");
106
+        final Integer value = (Integer) message.get("value");
107
+        //final Activity activity = QtNative.activity();
108
+	//final Service service = QtNative.service();
109
+	//final int JOB_ID = 1;
110
+        final int ONE_MIN = 60 * 1000;
111
+        Context context;
112
+        if (QtNative.activity() == null){
113
+		context = QtNative.service().getApplicationContext();
114
+		
115
+	} else {
116
+		context = QtNative.activity().getApplicationContext();
117
+	}
118
+        ComponentName component = new ComponentName(context, FriendiqaService.class);
119
+        JobInfo.Builder builder = new JobInfo.Builder(2, component)
120
+                // schedule it to run any time between 1 - 5 minutes
121
+                .setMinimumLatency(value * ONE_MIN)
122
+                .setOverrideDeadline((value + 5)*ONE_MIN)
123
+		//.setPeriodic(value * ONE_MIN)
124
+		.setRequiredNetworkType(JobInfo.NETWORK_TYPE_ANY);
125
+        JobScheduler jobScheduler = (JobScheduler) context.getSystemService(Context.JOB_SCHEDULER_SERVICE);
126
+        jobScheduler.schedule(builder.build());
127
+        
128
+        if (QtNative.service() != null){
129
+                Log.d(TAG,"Schedule Stopping Friendiqa Androidnative service");
130
+        ComponentName componentStopper = new ComponentName(context, FriendiqaStopService.class);
131
+        JobInfo.Builder stopbuilder = new JobInfo.Builder(1, componentStopper)
132
+                 .setMinimumLatency(50)
133
+                 .setOverrideDeadline(100);
134
+ 
135
+        JobScheduler jobStopScheduler = (JobScheduler) context.getSystemService(Context.JOB_SCHEDULER_SERVICE);
136
+        jobStopScheduler.schedule(stopbuilder.build());
137
+                
138
+                
139
+		//AndroidNativeService.stopQtService(context);
140
+        }
141
+	//context.stopService(new Intent(context, AndroidNativeService.class));
142
+    }
143
+
144
+    /**static void stopService(Map message){
145
+	this.stopService(new Intent(this, AndroidNativeService.class));
146
+    }
147
+    **/
87 148
 }

+ 2
- 0
source-android/application.qrc View File

@@ -225,5 +225,7 @@
225 225
         <file>qml/newsqml/ContactPage.qml</file>
226 226
         <file>qml/newsqml/NewsLink.qml</file>
227 227
         <file>qml/configqml/RegisterPage.qml</file>
228
+        <file>qml/newsqml/NewsYplayer.qml</file>
229
+        <file>js/yplayer.html</file>
228 230
     </qresource>
229 231
 </RCC>

+ 59
- 0
source-android/common/alarm.h View File

@@ -0,0 +1,59 @@
1
+//  This file is part of Friendiqa
2
+//  https://git.friendi.ca/lubuwest/Friendiqa
3
+//  Copyright (C) 2017 Marco R. <thomasschmidt45@gmx.net>
4
+//
5
+//  This program is free software: you can redistribute it and/or modify
6
+//  it under the terms of the GNU General Public License as published by
7
+//  the Free Software Foundation, either version 3 of the License, or
8
+//  (at your option) any later version.
9
+//
10
+//  In addition, as a special exception, the copyright holders give
11
+//  permission to link the code of portions of this program with the
12
+//  OpenSSL library under certain conditions as described in each
13
+//  individual source file, and distribute linked combinations including
14
+//  the two.
15
+//
16
+//  You must obey the GNU General Public License in all respects for all
17
+//  of the code used other than OpenSSL. If you modify file(s) with this
18
+//  exception, you may extend this exception to your version of the
19
+//  file(s), but you are not obligated to do so. If you do not wish to do
20
+//  so, delete this exception statement from your version. If you delete
21
+//  this exception statement from all source files in the program, then
22
+//  also delete it here.
23
+//
24
+//  This program is distributed in the hope that it will be useful,
25
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
26
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
27
+//  GNU General Public License for more details.
28
+//
29
+//  You should have received a copy of the GNU General Public License
30
+//  along with this program.  If not, see <http://www.gnu.org/licenses/>.
31
+
32
+#ifndef ALARM_H
33
+#define ALARM_H
34
+
35
+#include <QObject>
36
+
37
+class ALARM : public QObject
38
+{
39
+    Q_OBJECT
40
+    //Q_PROPERTY(int alarmtime READ alarmtime WRITE setAlarm NOTIFY alarmChanged)
41
+public:
42
+    static ALARM *instance();
43
+
44
+    explicit ALARM(QObject *parent = 0);
45
+  
46
+    //int alarmtime() const;
47
+
48
+signals:
49
+
50
+    void alarmChanged(QString url);
51
+
52
+public slots:
53
+    void setAlarm(int time);
54
+
55
+private:
56
+    int m_time;
57
+};
58
+
59
+#endif // UPDATENEWS_H

+ 82
- 0
source-android/common/alarmandroid.cpp View File

@@ -0,0 +1,82 @@
1
+//  This file is part of Friendiqa
2
+//  https://git.friendi.ca/lubuwest/Friendiqa
3
+//  Copyright (C) 2017 Marco R. <thomasschmidt45@gmx.net>
4
+//
5
+//  This program is free software: you can redistribute it and/or modify
6
+//  it under the terms of the GNU General Public License as published by
7
+//  the Free Software Foundation, either version 3 of the License, or
8
+//  (at your option) any later version.
9
+//
10
+//  In addition, as a special exception, the copyright holders give
11
+//  permission to link the code of portions of this program with the
12
+//  OpenSSL library under certain conditions as described in each
13
+//  individual source file, and distribute linked combinations including
14
+//  the two.
15
+//
16
+//  You must obey the GNU General Public License in all respects for all
17
+//  of the code used other than OpenSSL. If you modify file(s) with this
18
+//  exception, you may extend this exception to your version of the
19
+//  file(s), but you are not obligated to do so. If you do not wish to do
20
+//  so, delete this exception statement from your version. If you delete
21
+//  this exception statement from all source files in the program, then
22
+//  also delete it here.
23
+//
24
+//  This program is distributed in the hope that it will be useful,
25
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
26
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
27
+//  GNU General Public License for more details.
28
+//
29
+//  You should have received a copy of the GNU General Public License
30
+//  along with this program.  If not, see <http://www.gnu.org/licenses/>.
31
+
32
+//#include <QtAndroidExtras/QAndroidJniObject>
33
+//#include <QtAndroidExtras/QAndroidJniEnvironment>
34
+#include "alarm.h"
35
+#include <QtCore/QDebug>
36
+#include "AndroidNative/systemdispatcher.h"
37
+
38
+ALARM *ALARM::instance()
39
+{
40
+    static ALARM alarm;
41
+    return &alarm;
42
+}
43
+
44
+ALARM::ALARM(QObject *parent) : QObject(parent){}
45
+
46
+void ALARM::setAlarm(int interval)
47
+{
48
+    qDebug() << interval;
49
+    QVariantMap message;
50
+    message["value"] = interval;
51
+    AndroidNative::SystemDispatcher::instance()->loadClass("androidnative.Util");
52
+    AndroidNative::SystemDispatcher::instance()->dispatch("androidnative.Util.setSchedule", message);
53
+    //AndroidNative::SystemDispatcher::instance()->dispatch("androidnative.Util.stopService", message);
54
+//    auto activity = QtAndroid::androidActivity();
55
+//    auto packageManager = activity.callObjectMethod("getPackageManager",
56
+//                                                    "()Landroid/content/pm/PackageManager;");
57
+
58
+//    auto activityIntent = packageManager.callObjectMethod("getLaunchIntentForPackage",
59
+//                                                          "(Ljava/lang/String;)Landroid/content/Intent;",
60
+//                                                          activity.callObjectMethod("getPackageName",
61
+//                                                          "()Ljava/lang/String;").object());
62
+
63
+//    auto pendingIntent = QAndroidJniObject::callStaticObjectMethod("android/app/PendingIntent", "getActivity",
64
+//                                                                   "(Landroid/content/Context;ILandroid/content/Intent;I)Landroid/app/PendingIntent;",
65
+//                                                                   activity.object(), jint(0), activityIntent.object(),
66
+//                                                                   QAndroidJniObject::getStaticField<jint>("android/content/Intent",
67
+//                                                                                                           "FLAG_ACTIVITY_CLEAR_TOP"));
68
+
69
+//    auto alarmManager = activity.callObjectMethod("getSystemService",
70
+//                                                  "(Ljava/lang/String;)Ljava/lang/Object;",
71
+//                                                  QAndroidJniObject::getStaticObjectField("android/content/Context",
72
+//                                                                                          "ALARM_SERVICE",
73
+//                                                                                          "Ljava/lang/String;").object());
74
+
75
+//    alarmManager.callMethod<void>("set",
76
+//                                  "(IJLandroid/app/PendingIntent;)V",
77
+//                                  QAndroidJniObject::getStaticField<jint>("android/app/AlarmManager", "RTC"),
78
+//                                  jlong(QDateTime::currentMSecsSinceEpoch() + 100), pendingIntent.object());
79
+
80
+
81
+}
82
+

+ 23
- 1
source-android/common/friendiqa.cpp View File

@@ -31,10 +31,14 @@
31 31
 
32 32
 #include <QApplication>
33 33
 #include <QtQml/QQmlEngine>
34
+#include <QAndroidService>
35
+#include <QtAndroid>
34 36
 #include <QtQuick>
35 37
 #include "xhr.h"
38
+#include "updatenews.h"
36 39
 #include "filesystem.h"
37 40
 #include "remoteauthasyncimageprovider.h"
41
+#include "alarm.h"
38 42
 #include "AndroidNative/systemdispatcher.h"
39 43
 #include "AndroidNative/environment.h"
40 44
 //#include "AndroidNative/debug.h"
@@ -55,6 +59,20 @@ JNIEXPORT jint JNI_OnLoad(JavaVM* vm, void*) {
55 59
 
56 60
 
57 61
 int main(int argc, char *argv[]) {
62
+    //qDebug()<< "argv Friendiqa"<< argv[0] <<" argv2" <<argv[1];
63
+    if (qstrcmp(argv[1],"-service")==0){
64
+        //qDebug()<<"FriendiqaMain Service";
65
+        QAndroidService app(argc, argv);
66
+        UPDATENEWS* updatenews= UPDATENEWS::instance();
67
+        updatenews->setDatabase();
68
+        updatenews->login();
69
+        updatenews->timeline();
70
+        app.connect (updatenews,SIGNAL(quitapp()),&app,SLOT(quit()));
71
+        //QtAndroid::androidService().callMethod<void>("stopSelf");
72
+        return app.exec();
73
+    }
74
+    else{
75
+    
58 76
     QApplication app(argc, argv);
59 77
     QQuickView view;
60 78
     QTranslator qtTranslator;
@@ -67,10 +85,14 @@ int main(int argc, char *argv[]) {
67 85
     view.rootContext()->setContextProperty("xhr", xhr);
68 86
     FILESYSTEM* filesystem = FILESYSTEM::instance();
69 87
     view.rootContext()->setContextProperty("filesystem", filesystem);
88
+    ALARM* alarm = ALARM::instance();
89
+    view.rootContext()->setContextProperty("alarm", alarm);
90
+//    UPDATENEWS* updatenews = UPDATENEWS::instance();
91
+//    view.rootContext()->setContextProperty("updatenews", updatenews);
70 92
     view.setSource(QUrl("qrc:/qml/friendiqa.qml"));
71 93
     view.show();
72 94
     view.connect(view.rootContext()->engine(), SIGNAL(quit()), &app, SLOT(quit()));
73 95
     return app.exec();
74
-
96
+    }
75 97
 }
76 98
 

+ 399
- 0
source-android/common/updatenews.cpp View File

@@ -0,0 +1,399 @@
1
+//  This file is part of Friendiqa
2
+//  https://git.friendi.ca/lubuwest/Friendiqa
3
+//  Copyright (C) 2017 Marco R. <thomasschmidt45@gmx.net>
4
+//
5
+//  This program is free software: you can redistribute it and/or modify
6
+//  it under the terms of the GNU General Public License as published by
7
+//  the Free Software Foundation, either version 3 of the License, or
8
+//  (at your option) any later version.
9
+//
10
+//  In addition, as a special exception, the copyright holders give
11
+//  permission to link the code of portions of this program with the
12
+//  OpenSSL library under certain conditions as described in each
13
+//  individual source file, and distribute linked combinations including
14
+//  the two.
15
+//
16
+//  You must obey the GNU General Public License in all respects for all
17
+//  of the code used other than OpenSSL. If you modify file(s) with this
18
+//  exception, you may extend this exception to your version of the
19
+//  file(s), but you are not obligated to do so. If you do not wish to do
20
+//  so, delete this exception statement from your version. If you delete
21
+//  this exception statement from all source files in the program, then
22
+//  also delete it here.
23
+//
24
+//  This program is distributed in the hope that it will be useful,
25
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
26
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
27
+//  GNU General Public License for more details.
28
+//
29
+//  You should have received a copy of the GNU General Public License
30
+//  along with this program.  If not, see <http://www.gnu.org/licenses/>.
31
+
32
+#include "updatenews.h"
33
+
34
+#include <QHttpPart>
35
+#include <QTextCodec>
36
+#include <QUrlQuery>
37
+#include <QList>
38
+#include <QDataStream>
39
+#include <QJsonDocument>
40
+#include <QJsonObject>
41
+#include <QJsonArray>
42
+#include <QQmlEngine>
43
+#include <QSqlQuery>
44
+#include <QSqlRecord>
45
+#include <QSqlDatabase>
46
+#include <QSqlError>
47
+#include <QDateTime>
48
+//#include "AndroidNative/systemdispatcher.h"
49
+
50
+
51
+
52
+UPDATENEWS *UPDATENEWS::instance()
53
+{
54
+    static UPDATENEWS udn;
55
+    return &udn;
56
+}
57
+
58
+UPDATENEWS::UPDATENEWS(QObject *parent) : QObject(parent)
59
+{
60
+
61
+}
62
+
63
+void UPDATENEWS::setUrl(QString url)
64
+{
65
+   if (url!=m_url) {
66
+       m_url = url;
67
+       xhr.setUrl(url);
68
+       emit urlChanged(m_url);
69
+   }
70
+}
71
+
72
+
73
+void UPDATENEWS::setDatabase()
74
+{
75
+    static QQmlEngine qe;
76
+    QString db_url=qe.offlineStorageDatabaseFilePath("Friendiqa");
77
+    m_db = QSqlDatabase::addDatabase("QSQLITE");
78
+    m_db.setDatabaseName(QUrl("file://"+db_url+".sqlite").toLocalFile());
79
+    //qDebug() << db_url;
80
+
81
+      if (!m_db.open())
82
+      {
83
+         qDebug() << "Error: connection with database fail " << m_db.lastError();
84
+      }
85
+}
86
+
87
+
88
+void UPDATENEWS::login()
89
+{
90
+    QSqlQuery query("SELECT * FROM config WHERE isActive=0",m_db);
91
+    while (query.next())
92
+    {
93
+       username = query.value(1).toString();
94
+       QByteArray bpassword=query.value(2).toByteArray();
95
+       QString password=QByteArray::fromBase64(bpassword);
96
+       m_login=username+":"+password ;
97
+       xhr.setLogin(m_login);
98
+       m_url=query.value(0).toString();
99
+       xhr.setUrl(m_url);
100
+       m_imagedir=query.value(3).toString();
101
+       xhr.setImagedir(m_imagedir);
102
+       QString isActive=query.value(7).toString();
103
+       m_updateInterval=query.value(5).toInt(); 
104
+       m_api="/api/statuses/friends_timeline";
105
+       xhr.setApi(m_api);
106
+    }
107
+}
108
+
109
+
110
+void UPDATENEWS::timeline()
111
+{
112
+    qDebug()<<"Friendiqa start timeline";
113
+    QSqlQuery query("SELECT status_id FROM news WHERE username='"+ username +"' ORDER BY status_id DESC LIMIT 1",m_db);
114
+    if (query.isActive() && query.isSelect()){query.first();};
115
+    QString lastid=query.value(0).toString();
116
+    xhr.clearParams();
117
+    xhr.setParam("since_id",lastid);
118
+    xhr.setParam("count","50");
119
+    xhr.get();
120
+    QObject::connect(&xhr,SIGNAL(success(QByteArray,QString)),this,SLOT(store(QByteArray,QString)));
121
+    QObject::connect(&xhr,SIGNAL(error(QString,QString,QString,int)),this,SLOT(showError(QString,QString,QString,int)));
122
+}
123
+
124
+
125
+//void UPDATENEWS::startservice(QString type,QVariantMap map)
126
+//{
127
+//    qDebug ()<<"Friediqa start service "<<type;
128
+//    if (type=="androidnativeServiceStarted"){
129
+//        setDatabase();
130
+//        login();
131
+//        timeline();
132
+//    }
133
+//}
134
+
135
+void UPDATENEWS::store(QByteArray serverreply,QString apiname)
136
+{
137
+    QJsonDocument news;
138
+    qDebug()<<apiname << news;
139
+    QJsonParseError jsonerror;
140
+    news=QJsonDocument::fromJson(serverreply,&jsonerror);
141
+    if (news.isArray()){
142
+        for (int i=0; i < news.array().count();i++){
143
+            QJsonValue newsitem=news[i];
144
+            QSqlQuery query(m_db);
145
+            query.prepare("INSERT INTO news (username,messagetype,text,created_at,in_reply_to_status_id,source,status_id,in_reply_to_user_id,geo,favorited,uid,statusnet_html,statusnet_conversation_id,friendica_activities,friendica_activities_self,attachments,friendica_owner) " "VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)");
146
+            query.bindValue(0,username);
147
+            query.bindValue(1,"0");
148
+            query.bindValue(2, newsitem["text"].toString().toUtf8().toBase64());
149
+            QString sourcedate=newsitem["created_at"].toString();
150
+            QString formateddate=sourcedate.mid(0,3)+", "+sourcedate.mid(8,3)+sourcedate.mid(4,3)+sourcedate.mid(25,5)+sourcedate.mid(10,15);
151
+            query.bindValue(3,QDateTime::fromString(formateddate,Qt::RFC2822Date).toMSecsSinceEpoch() );
152
+            if(newsitem["in_reply_to_status_id"]!=QJsonValue::Null){query.bindValue(4, newsitem["in_reply_to_status_id"].toInt());};
153
+            query.bindValue(5,newsitem["source"]);
154
+            query.bindValue(6,newsitem["id"].toInt());
155
+            if(newsitem["in_reply_to_user_id"]!=QJsonValue::Null){ query.bindValue(7,newsitem["in_reply_to_user_id"].toInt());};
156
+            query.bindValue(8,newsitem["geo"]);
157
+            query.bindValue( 9, newsitem["favorited"].toInt());
158
+            query.bindValue(10, newsitem["user"]["id"].toInt());
159
+            query.bindValue(11, newsitem["statusnet_html"].toString().toUtf8().toBase64());
160
+            query.bindValue(12, newsitem["statusnet_conversation_id"].toInt());
161
+            QJsonArray likeArray;QJsonArray dislikeArray;QJsonArray attendyesArray;QJsonArray attendnoArray;QJsonArray attendmaybeArray;
162
+            if (newsitem.toObject().contains("friendica_activities")){
163
+                for (int a=0; a < newsitem["friendica_activities"]["like"].toArray().count();a++){
164
+                    likeArray.append(newsitem["friendica_activities"]["like"][a]["url"].toString());
165
+                }
166
+                for (int b=0; b < newsitem["friendica_activities"]["dislike"].toArray().count();b++){
167
+                    dislikeArray.append(newsitem["friendica_activities"]["dislike"][b]["url"].toString());
168
+                }
169
+                for (int c=0; c < newsitem["friendica_activities"]["attendyes"].toArray().count();c++){
170
+                    attendyesArray.append(newsitem["friendica_activities"]["attendyes"][c]["url"].toString());
171
+                }
172
+                for (int d=0; d < newsitem["friendica_activities"]["attendno"].toArray().count();d++){
173
+                    attendnoArray.append(newsitem["friendica_activities"]["attendno"][d]["url"].toString());
174
+                }
175
+                for (int e = 0; e < newsitem["friendica_activities"]["attendmaybe"].toArray().count();e++){
176
+                    attendmaybeArray.append(newsitem["friendica_activities"]["attendmaybe"][e]["url"].toString());
177
+                }
178
+             };
179
+            QJsonArray friendica_activities; friendica_activities={likeArray,dislikeArray,attendyesArray,attendnoArray,attendmaybeArray};
180
+            QJsonDocument activities; activities.setArray(friendica_activities);
181
+            query.bindValue(13,activities.toJson(QJsonDocument::Compact).toBase64());
182
+            query.bindValue(14,"[]");
183
+
184
+            if (newsitem["attachments"]!=QJsonValue::Undefined){
185
+                query.bindValue(15, QJsonDocument(newsitem["attachments"].toArray()).toJson(QJsonDocument::Compact).toBase64());
186
+            };
187
+
188
+            query.bindValue(16, newsitem["friendica_owner"]["url"]);
189
+            query.exec() ;
190
+        }
191
+    }
192
+    else {
193
+        qDebug()<< "Friendiqa updatenews error";
194
+        emit this->error(m_api,QTextCodec::codecForName("utf-8")->toUnicode(serverreply));
195
+        if(m_updateInterval!=0){
196
+            m_db.close();
197
+            m_db.removeDatabase(m_db.connectionName());
198
+            emit quitapp();
199
+            alarm.setAlarm(m_updateInterval);
200
+        };
201
+    }
202
+    QList<QJsonValue> newcontacts=findNewContacts(news);
203
+    updateContacts(newcontacts);
204
+    startImagedownload();
205
+    connect(&xhr, SIGNAL(downloaded(QString, QString, QString, int)), this, SLOT(updateImageLocation(QString,QString, QString, int)));
206
+
207
+}
208
+
209
+void UPDATENEWS::updateImageLocation(QString downloadtype,QString imageurl, QString filename, int index){
210
+    if (downloadtype=="contactlist"){
211
+        QSqlQuery testquery("SELECT profile_image FROM contacts WHERE profile_image_url ='"+imageurl+ "' AND username = '" +username+"'",m_db);
212
+        testquery.exec();
213
+        //qDebug()<< "update imageurl for " <<imageurl << " from " <<testquery.value(0).toString() <<" to "<< filename <<" index " << index << " newcontactnames.length " <<newcontactnames.length();
214
+        QSqlQuery query("UPDATE contacts SET profile_image='"+ filename +"' WHERE profile_image_url ='"+imageurl+ "' AND username = '" +username+"'",m_db);
215
+        query.exec();
216
+        if (index==(newcontactnames.length()-1)){
217
+            if(m_updateInterval!=0){
218
+                m_db.close();
219
+                m_db.removeDatabase(m_db.connectionName());
220
+                emit quitapp();
221
+                alarm.setAlarm(m_updateInterval);
222
+            };
223
+        }
224
+    }
225
+}
226
+
227
+QList <QJsonValue> UPDATENEWS::findNewContacts(QJsonDocument news){
228
+    QSqlQuery query("SELECT profile_image_url FROM contacts",m_db);
229
+    QList<QString> imageurls;
230
+    while (query.next()){
231
+        imageurls.append(query.value(0).toString());
232
+    }
233
+    QList<QJsonValue> newcontacts;
234
+    qDebug()<<"updatenews findcontacts count "<<news.array().count();
235
+
236
+    for (int i=0; i<news.array().count();i++){
237
+        //main contacts
238
+        if(imageurls.contains(news[i]["user"]["profile_image_url"].toString()) || newcontactimagelinks.contains(news[i]["user"]["profile_image_url"].toString())){
239
+            }
240
+        else{
241
+            newcontacts.append(news[i]["user"]);
242
+            newcontactimagelinks.append(news[i]["user"]["profile_image_url"].toString());
243
+            newcontactnames.append(news[i]["user"]["screen_name"].toString());
244
+        }
245
+        //like/dislike contacts
246
+        if (news[i].toObject().contains("friendica_activities") ){
247
+            for (int a=0; a < news[i]["friendica_activities"]["like"].toArray().count();a++){
248
+                if(imageurls.contains(news[i]["friendica_activities"]["like"][a]["profile_image_url"].toString()) || newcontactimagelinks.contains(news[i]["friendica_activities"]["like"][a]["profile_image_url"].toString())){
249
+                    }
250
+                else{
251
+                    newcontacts.append(news[i]["friendica_activities"]["like"][a]);
252
+                    newcontactimagelinks.append(news[i]["friendica_activities"]["like"][a]["profile_image_url"].toString());
253
+                    newcontactnames.append(news[i]["friendica_activities"][a]["screen_name"].toString());
254
+                }
255
+            }
256
+            for (int b=0; b < news[i]["friendica_activities"]["dislike"].toArray().count();b++){
257
+                if(imageurls.contains(news[i]["friendica_activities"]["dislike"][b]["profile_image_url"].toString()) || newcontactimagelinks.contains(news[i]["friendica_activities"]["dislike"][b]["profile_image_url"].toString())){
258
+                    }
259
+                else{
260
+                    newcontacts.append(news[i]["friendica_activities"]["dislike"][b]);
261
+                    newcontactimagelinks.append(news[i]["friendica_activities"]["dislike"][b]["profile_image_url"].toString());
262
+                    newcontactnames.append(news[i]["friendica_activities"][b]["screen_name"].toString());
263
+                }
264
+            }
265
+        }
266
+        //owner contacts
267
+        if (news[i].toObject().contains("friendica_owner") ){
268
+            if(imageurls.contains(news[i]["friendica_owner"]["profile_image_url"].toString()) || newcontactimagelinks.contains(news[i]["friendica_owner"]["profile_image_url"].toString())){
269
+                }
270
+            else{
271
+                newcontacts.append(news[i]["friendica_owner"]);
272
+                newcontactimagelinks.append(news[i]["friendica_owner"]["profile_image_url"].toString());
273
+                newcontactnames.append(news[i]["friendica_owner"]["screen_name"].toString());
274
+            }
275
+          }
276
+    }
277
+    return newcontacts;
278
+}
279
+
280
+
281
+void UPDATENEWS::updateContacts(QList<QJsonValue> contacts){
282
+    qint64 currentTime =QDateTime::currentMSecsSinceEpoch();
283
+    for (int i=0; i < contacts.count();i++){
284
+        QJsonValue contact=contacts[i];
285
+        QSqlQuery query(m_db);
286
+        //qDebug() << "updatecontact " << contact["screen_name"];
287
+        QSqlQuery testquery("SELECT url FROM contacts WHERE username='"+ username +"' AND url='" + contact["url"].toString() +"'",m_db);
288
+        if (testquery.first()){
289
+            query.prepare("UPDATE contacts SET id=?, name=?, screen_name=?, location=?,imageAge=?,"
290
+                      "profile_image_url=?, description=?, protected=?, followers_count=?,"
291
+                      "friends_count=?, created_at=?, favourites_count=?, utc_offset=?, time_zone=?, statuses_count=?,"
292
+                      "following=?, verified=?, statusnet_blocking=?, notifications=?, statusnet_profile_url=?, cid=?, network=?, timestamp=? "
293
+                      " WHERE username='"+ username +"' AND url='" + contact["url"].toString() +"'");
294
+            query.bindValue(0, contact["id"].toInt());
295
+            query.bindValue(1, contact["name"].toString().toUtf8().toBase64());
296
+            query.bindValue(2, contact["screen_name"]);
297
+            query.bindValue(3, contact["location"]);
298
+            query.bindValue(4, currentTime);
299
+            query.bindValue(5, contact["profile_image_url"]);
300
+            if(contact["description"].isNull() ){query.bindValue(6,"");}else{query.bindValue(6, contact["description"].toString().toUtf8().toBase64());};
301
+            query.bindValue(7,contact["protected"].toBool());
302
+            query.bindValue(8,contact["followers_count"].toInt());
303
+            query.bindValue(9,contact["friends_count"].toInt());
304
+            QString sourcedate=contact["created_at"].toString();
305
+            QString formateddate=sourcedate.mid(0,3)+", "+sourcedate.mid(8,3)+sourcedate.mid(4,3)+sourcedate.mid(25,5)+sourcedate.mid(10,15);
306
+            query.bindValue(10,QDateTime::fromString(formateddate,Qt::RFC2822Date).toMSecsSinceEpoch() );
307
+            query.bindValue(11,contact["favorites_count"].toInt());
308
+            query.bindValue(12,contact["utc_offset"].toInt());
309
+            query.bindValue(13,contact["time_zone"].toString());
310
+            query.bindValue(14,contact["statuses_count"].toInt());
311
+            query.bindValue(15,contact["following"].toBool());
312
+            query.bindValue(16,contact["verfied"].toBool());
313
+            query.bindValue(17,contact["statusnet_blocking"].toBool());
314
+            query.bindValue(18,contact["notifications"].toBool());
315
+            query.bindValue(19,contact["statusnet_profile_url"]);
316
+            query.bindValue(20,contact["cid"].toInt());
317
+            query.bindValue(21,contact["network"]);
318
+            qint64 timestamp=0;
319
+            QString timestamphelper=contact["profile_image_url"].toString();
320
+            try {timestamp=timestamphelper.mid(timestamphelper.indexOf("?ts")+4,timestamphelper.length()).toUInt();} catch(...){};
321
+            query.bindValue(22,timestamp);
322
+        }
323
+
324
+        else{
325
+            query.prepare("INSERT INTO contacts (username, id, name, screen_name, location,imageAge,"
326
+                      "profile_image_url, description, profile_image, url, protected, followers_count,"
327
+                      "friends_count, created_at, favourites_count, utc_offset, time_zone, statuses_count,"
328
+                      "following, verified, statusnet_blocking, notifications, statusnet_profile_url, cid, network, isFriend, timestamp)"
329
+                      "VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)");
330
+
331
+            query.bindValue(0,username);
332
+            query.bindValue(1, contact["id"].toInt());
333
+            query.bindValue(2, contact["name"].toString().toUtf8().toBase64());
334
+            query.bindValue(3, contact["screen_name"]);
335
+            query.bindValue(4, contact["location"]);
336
+            query.bindValue(5, currentTime);
337
+            query.bindValue(6, contact["profile_image_url"]);
338
+            if(contact["description"].isNull() ){query.bindValue(7,"");}else{query.bindValue(7, contact["description"].toString().toUtf8().toBase64());};
339
+            query.bindValue(8,"none");
340
+            query.bindValue(9, contact["url"].toString());
341
+            query.bindValue(10,contact["protected"].toBool());
342
+            query.bindValue(11,contact["followers_count"].toInt());
343
+            query.bindValue(12,contact["friends_count"].toInt());
344
+            QString sourcedate=contact["created_at"].toString();
345
+            QString formateddate=sourcedate.mid(0,3)+", "+sourcedate.mid(8,3)+sourcedate.mid(4,3)+sourcedate.mid(25,5)+sourcedate.mid(10,15);
346
+            query.bindValue(13,QDateTime::fromString(formateddate,Qt::RFC2822Date).toMSecsSinceEpoch() );
347
+            query.bindValue(14,contact["favorites_count"].toInt());
348
+            query.bindValue(15,contact["utc_offset"].toInt());
349
+            query.bindValue(16,contact["time_zone"].toString());
350
+            query.bindValue(17,contact["statuses_count"].toInt());
351
+            query.bindValue(18,contact["following"].toBool());
352
+            query.bindValue(19,contact["verfied"].toBool());
353
+            query.bindValue(20,contact["statusnet_blocking"].toBool());
354
+            query.bindValue(21,contact["notifications"].toBool());
355
+            query.bindValue(22,contact["statusnet_profile_url"]);
356
+            query.bindValue(23,contact["cid"].toInt());
357
+            query.bindValue(24,contact["network"]);
358
+            query.bindValue(25, 0);
359
+            qint64 timestamp=0;
360
+            QString timestamphelper=contact["profile_image_url"].toString();
361
+            try {timestamp=timestamphelper.mid(timestamphelper.indexOf("?ts")+4,timestamphelper.length()).toUInt();} catch(...){};
362
+            query.bindValue(26,timestamp);
363
+
364
+        }
365
+        query.exec() ;
366
+    }
367
+        emit this->success(m_api);
368
+    if ((contacts.count()==0) && (m_updateInterval!=0)){
369
+        m_db.close();
370
+        m_db.removeDatabase(m_db.connectionName());
371
+        emit quitapp();
372
+        alarm.setAlarm(m_updateInterval);
373
+    };
374
+}
375
+
376
+QString UPDATENEWS::url() const
377
+{
378
+    return m_url;
379
+}
380
+
381
+void UPDATENEWS::startImagedownload()
382
+{
383
+    xhr.setDownloadtype("contactlist");
384
+    xhr.setFilelist(newcontactimagelinks);
385
+    xhr.setContactlist(newcontactnames);
386
+    xhr.setImagedir(m_imagedir);
387
+    xhr.getlist();
388
+}
389
+
390
+void UPDATENEWS::showError(QString data, QString url,QString api, int code )
391
+{
392
+    emit this->error(api,data);
393
+    if(m_updateInterval!=0){
394
+        m_db.close();
395
+        m_db.removeDatabase(m_db.connectionName());
396
+        emit quitapp();
397
+        alarm.setAlarm(m_updateInterval);
398
+    };
399
+}

+ 92
- 0
source-android/common/updatenews.h View File

@@ -0,0 +1,92 @@
1
+//  This file is part of Friendiqa
2
+//  https://git.friendi.ca/lubuwest/Friendiqa
3
+//  Copyright (C) 2017 Marco R. <thomasschmidt45@gmx.net>
4
+//
5
+//  This program is free software: you can redistribute it and/or modify
6
+//  it under the terms of the GNU General Public License as published by
7
+//  the Free Software Foundation, either version 3 of the License, or
8
+//  (at your option) any later version.
9
+//
10
+//  In addition, as a special exception, the copyright holders give
11
+//  permission to link the code of portions of this program with the
12
+//  OpenSSL library under certain conditions as described in each
13
+//  individual source file, and distribute linked combinations including
14
+//  the two.
15
+//
16
+//  You must obey the GNU General Public License in all respects for all
17
+//  of the code used other than OpenSSL. If you modify file(s) with this
18
+//  exception, you may extend this exception to your version of the
19
+//  file(s), but you are not obligated to do so. If you do not wish to do
20
+//  so, delete this exception statement from your version. If you delete
21
+//  this exception statement from all source files in the program, then
22
+//  also delete it here.
23
+//
24
+//  This program is distributed in the hope that it will be useful,
25
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
26
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
27
+//  GNU General Public License for more details.
28
+//
29
+//  You should have received a copy of the GNU General Public License
30
+//  along with this program.  If not, see <http://www.gnu.org/licenses/>.
31
+
32
+#ifndef UPDATENEWS_H
33
+#define UPDATENEWS_H
34
+
35
+#include <QObject>
36
+#include <QJsonObject>
37
+#include <QSqlDatabase>
38
+#include "xhr.h"
39
+#include "alarm.h"
40
+#include "AndroidNative/systemdispatcher.h"
41
+
42
+class UPDATENEWS : public QObject
43
+{
44
+    Q_OBJECT
45
+    Q_PROPERTY(QString url READ url WRITE setUrl NOTIFY urlChanged)
46
+//    Q_PROPERTY(QString login READ login NOTIFY loginChanged)
47
+public:
48
+    static UPDATENEWS *instance();
49
+
50
+    explicit UPDATENEWS(QObject *parent = 0);
51
+  
52
+    QString url() const;
53
+    //QString login() const;
54
+
55
+signals:
56
+
57
+    void urlChanged(QString url);
58
+    void success(QString api);
59
+    void error(QString api, QString content);
60
+    void quitapp();
61
+
62
+public slots:
63
+    void setUrl(QString url);
64
+    void setDatabase();
65
+    void login();
66
+    void timeline();
67
+    //void startservice(QString type,QVariantMap map);
68
+    void startImagedownload();
69
+    void updateImageLocation(QString downloadtype,QString imageurl, QString filename, int index);
70
+    void store(QByteArray serverreply,QString apiname);
71
+    void showError(QString data, QString url,QString api, int code);
72
+
73
+private:
74
+    QString m_url;
75
+    QString m_api;
76
+    QString m_imagedir;
77
+    QString m_login;
78
+    QString username;
79
+    QSqlDatabase m_db;
80
+    QList<QJsonValue> findNewContacts(QJsonDocument news);
81
+    int m_updateInterval;
82
+    //void timeline();
83
+    //void store(QByteArray serverreply,QString apiname);
84
+    void updateContacts(QList<QJsonValue> contacts);
85
+
86
+    XHR xhr;
87
+    ALARM alarm;
88
+    QList<QString> newcontactimagelinks;
89
+    QList<QString> newcontactnames;
90
+};
91
+
92
+#endif // UPDATENEWS_H

+ 1
- 1
source-android/common/xhr.cpp View File

@@ -290,7 +290,7 @@ void XHR::onReplyError(QNetworkReply::NetworkError code)
290 290
 void XHR::onReplySuccess()
291 291
 {
292 292
     qDebug() << "!";
293
-    emit this->success( bufferToString(), m_api);
293
+    emit this->success(buffer, m_api);
294 294
     buffer.clear();
295 295
 //    reply->deleteLater();
296 296
 }

+ 1
- 1
source-android/common/xhr.h View File

@@ -79,7 +79,7 @@ signals:
79 79
     void networktypeChanged();
80 80
     void downloaded(QString type, QString url, QString filename, int i);
81 81
     void downloadedjson(QString type, QString url, QString filename, int i,QJsonObject jsonObject);
82
-    void success(QString data, QString api);
82
+    void success(QByteArray data, QString api);
83 83
     void error(QString data, QString url,QString api, int code);
84 84
 
85 85
 public slots:

+ 9
- 4
source-android/friendiqa.pro View File

@@ -21,7 +21,9 @@ SOURCES += common/friendiqa.cpp \
21 21
 	common/uploadableimage.cpp \
22 22
 	common/xhr.cpp \
23 23
         common/filesystem.cpp \
24
-        common/remoteauthasyncimageprovider.cpp
24
+        common/remoteauthasyncimageprovider.cpp \
25
+        common/updatenews.cpp \
26
+        common/alarmandroid.cpp
25 27
 
26 28
 ANDROID_PACKAGE_SOURCE_DIR = $$PWD/android
27 29
 
@@ -38,14 +40,17 @@ OTHER_FILES += qml/friendiqa.qml \
38 40
     js/*.js
39 41
 
40 42
 TRANSLATIONS += translations/friendiqa-de.ts \
41
-                translations/friendiqa-es.ts
43
+                translations/friendiqa-es.ts \
44
+                translations/friendiqa-it.ts
42 45
 
43 46
 HEADERS += \
44 47
     common/uploadableimage.h \
45 48
     common/xhr.h \
46 49
     common/filesystem.h \
47
-    common/remoteauthasyncimageprovider.h
48
-    
50
+    common/remoteauthasyncimageprovider.h \
51
+    common/updatenews.h \
52
+    common/alarm.h
53
+
49 54
 DISTFILES += \
50 55
     qml/calendarqml/*.qml \
51 56
     android/AndroidManifest.xml \

+ 14
- 0
source-android/js/helper.js View File

@@ -95,6 +95,20 @@ function friendicaWebRequest(url,rootwindow,callback) {
95 95
     xhrequest.send();
96 96
 }
97 97
 
98
+function friendicaXmlRequest(url,rootwindow,callback) {
99
+    var xhrequest = new XMLHttpRequest();
100
+    xhrequest.onreadystatechange = function() {
101
+        if (xhrequest.readyState === XMLHttpRequest.HEADERS_RECEIVED) {}
102
+        else if(xhrequest.readyState === XMLHttpRequest.DONE) {
103
+            try{callback(xhrequest.responseXML)}
104
+            catch (e){showMessage("Error","API:\n" +url+" "+e+"\n Return: "+xhrequest.responseText, rootwindow)}
105
+         }
106
+    }
107
+    xhrequest.open("GET", url);
108
+    xhrequest.responseType ="document";
109
+    xhrequest.send();
110
+}
111
+
98 112
 function friendicaRemoteAuthRequest(login,url,c_url,rootwindow,callback) {
99 113
     var xhrequest = new XMLHttpRequest();
100 114
     xhrequest.onreadystatechange = function() {

+ 1
- 1
source-android/js/news.js View File

@@ -465,7 +465,7 @@ function chatsfromdb(database,user,callback,stop_time){
465 465
         helpernews.statusnet_html=Qt.atob(helpernews.statusnet_html);
466 466
         helpernews.text=Qt.atob(helpernews.text);
467 467
         helpernews.id=helpernews.status_id;
468
-        if (helpernews.attachments!==null){print(Qt.atob(helpernews.attachments));helpernews.attachments=JSON.parse(Qt.atob(helpernews.attachments))};
468
+        if (helpernews.attachments!==null){helpernews.attachments=JSON.parse(Qt.atob(helpernews.attachments))};
469 469
         newsArray.push(helpernews);
470 470
     }
471 471
     callback(newsArray);

+ 15
- 0
source-android/js/newsworker.js View File

@@ -135,6 +135,21 @@ else{
135 135
                if ((attachmentList.length==0) || (attachmentList[attachmentList.length-1].url!=ptvideohelper.url)){attachmentList.push(ptvideohelper)}
136 136
            }
137 137
       }
138
+//      if (newsitemobject.text.indexOf("https://www.youtube.com/watch")>-1){
139
+//            //print("message "+msg.options.showWebsiteForLinks);
140
+//           if (msg.options.showYoutube!="false"){
141
+//               var ythelper={mimetype:"video/youtube"}
142
+//               var yttext=newsitemobject.text;
143
+//               while (yttext.indexOf("https://www.youtube.com/watch")>-1){
144
+//                   var ythelperstringposition=linktext.indexOf("watch?v=");
145
+//                   var ytposend=findend(yttext,ythelperstringposition);
146
+//                   ythelper.url=yttext.substring(yttext.lastIndexOf("http",linkhelperstringposition),linkposend);
147
+//                   linktext=linktext.substring(linkhelperstringposition+5,linktext.length)
148
+//                   if ((attachmentList.length==0) || (attachmentList[attachmentList.length-1].url!=linkhelper.url)){attachmentList.push(linkhelper)}
149
+//               }
150
+//           }
151
+//      }
152
+      
138 153
 //        if (newsitemobject.text.indexOf(".html")>-1){
139 154
 //            //print("message "+msg.options.showWebsiteForLinks);
140 155
 //           if (msg.options.showWebsiteForLinks!="false"){

+ 7
- 7
source-android/js/service.js View File

@@ -513,9 +513,6 @@ function updateView(viewtype){
513 513
     //downloadNotice.text="xhr start "+Date.now()
514 514
     switch(viewtype){
515 515
         case "Conversations":
516
-//            updatenews.setDatabase();
517
-//            updatenews.login();
518
-//            updatenews.timeline();
519 516
             var lastnews=Newsjs.getLastNews(login,db);
520 517
             xhr.setLogin(login.username+":"+Qt.atob(login.password));
521 518
             xhr.setUrl(login.server);
@@ -525,9 +522,6 @@ function updateView(viewtype){
525 522
             xhr.setParam("count",50)
526 523
             break;
527 524
         case "Timeline":
528
-//             updatenews.setDatabase();
529
-//            updatenews.login();
530
-//            updatenews.timeline();
531 525
             var lastnews=Newsjs.getLastNews(login,db);
532 526
             xhr.setLogin(login.username+":"+Qt.atob(login.password));
533 527
             xhr.setUrl(login.server);
@@ -565,6 +559,12 @@ function updateView(viewtype){
565 559
             xhr.setApi("/api/favorites");
566 560
             xhr.clearParams();
567 561
             break;
562
+        case "Replies":
563
+            xhr.setLogin(login.username+":"+Qt.atob(login.password));
564
+            xhr.setUrl(login.server);
565
+            xhr.setApi("/api/statuses/replies");
566
+            xhr.clearParams();
567
+            break;
568 568
         default:
569 569
             var lastnews=Newsjs.getLastNews(login,db);
570 570
             xhr.setLogin(login.username+":"+Qt.atob(login.password));
@@ -575,8 +575,8 @@ function updateView(viewtype){
575 575
             xhr.setParam("count",50)
576 576
             newstab.newstabstatus="Conversations";
577 577
     }
578
-    xhr.get();
579 578
 
579
+    xhr.get();
580 580
     if (viewtype==="Conversations"){Newsjs.allchatsfromdb(db,login.username,function(temp){
581 581
         newsStack.allchats=temp
582 582
     })}

+ 45
- 0
source-android/js/yplayer.html View File

@@ -0,0 +1,45 @@
1
+<html>
2
+  <head>
3
+    <title>-1</title>
4
+    <meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no"/>
5
+  </head>
6
+  <body bgcolor="black" marginwidth="0" marginheight="0">
7
+    <div id="player"></div>
8
+    <script>
9
+        function getVideoId() {
10
+          return window.location.href.slice(window.location.href.indexOf('?') + 1);
11
+        }
12
+        var tag = document.createElement('script');
13
+        tag.src = "https://www.youtube.com/iframe_api";
14
+        var firstScriptTag = document.getElementsByTagName('script')[0];
15
+        firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);
16
+        
17
+        var player;
18
+        function onYouTubeIframeAPIReady() {
19
+          player = new YT.Player('player', {
20
+            playerVars: { 'html5': 1, 'iv_load_policy': 3 },
21
+            frameborder: '0',
22
+            height: '100%',
23
+            width: '100%',
24
+            videoId: getVideoId(),
25
+            events: {
26
+              'onReady': onPlayerReady,
27
+              'onStateChange': onPlayerStateChange
28
+            }
29
+          });
30
+        }
31
+        
32
+        function onPlayerReady(event) {
33
+          document.title = 0;
34
+        }
35
+
36
+        function onPlayerStateChange(event) {
37
+          if (event.data == YT.PlayerState.PLAYING) {
38
+            document.title = 1;
39
+          } else if (event.data == YT.PlayerState.ENDED || event.data == YT.PlayerState.PAUSED) {
40
+            document.title = 2;
41
+          }
42
+        }
43
+    </script>
44
+  </body>
45
+</html>

+ 143
- 127
source-android/qml/configqml/ConfigTab.qml View File

@@ -93,99 +93,106 @@ StackView{
93 93
             }
94 94
 
95 95
     Text {
96
-      text: qsTr("Server")
97
-     x: 4*mm; y: 10*mm
96
+        text: qsTr("Server")
97
+        font.pixelSize:3*mm
98
+        x: 4*mm; y: 10*mm
98 99
     }
99 100
     Text {
100
-      text: qsTr("Nickname")
101
-     x: 4*mm; y: 20*mm
101
+        text: qsTr("Nickname")
102
+        font.pixelSize:3*mm
103
+        x: 4*mm; y: 20*mm
102 104
     }
103 105
 
104 106
     Text {
105 107
         text: qsTr("Password")
106
-       x: 4*mm; y: 30*mm
108
+        font.pixelSize:3*mm
109
+        x: 4*mm; y: 30*mm
107 110
       }
108 111
     Text {
109
-       text: qsTr("Image dir.")
110
-      x: 4*mm; y: 40*mm
112
+        text: qsTr("Image dir.")
113
+        font.pixelSize:3*mm
114
+        x: 4*mm; y: 40*mm
111 115
      }
112 116
 
113
-   Text {
114
-       text: qsTr("Max. News")
115
-      x: 4*mm; y: 50*mm
116
-     }
117
-   Text {
118
-       text: qsTr("News as")
119
-      x: 4*mm; y: 60*mm
117
+    Text {
118
+        text: qsTr("Max. News")
119
+        font.pixelSize:3*mm
120
+        x: 4*mm; y: 50*mm
120 121
      }
121 122
     Text {
122
-        text: qsTr("Interval (0=None)")
123
-        visible: false
124
-        x: 4*mm; y: 70*mm; width:20*mm;wrapMode: Text.Wrap
125
-      }
123
+        text: qsTr("News as")
124
+        font.pixelSize:3*mm
125
+        x: 4*mm; y: 60*mm
126
+    }
127
+    Text {
128
+        text: qsTr("Sync Interval (0=None)")
129
+        font.pixelSize:3*mm
130
+        //visible: false
131
+        x: 4*mm; y: 70*mm; //width:35*mm;wrapMode: Text.Wrap
132
+    }
126 133
       
127
-//      Text {
134
+//    Text {
128 135
 //          text: qsTr("Show Website")
129
-//          x: 4*mm; y: 70*mm; width: 20*mm
130
-//      }
131
-
132
-        Image{
133
-            id:servericon
134
-            x:19*mm;y:10*mm
135
-            width:5*mm; height: 5*mm
136
-            visible: false
137
-            source:""
138
-            MouseArea{
139
-                anchors.fill:parent
140
-                onClicked:{
141
-                    Service.showServerConfig(servername.text, configBackground, function(configString){
142
-                    var serverconfigObject=Qt.createQmlObject(configString,configBackground,"serverconfigOutput");})
143
-                }
144
-            }
145
-        }
136
+//          x: 4*mm; y:80*mm; width: 20*mm
137
+//    }
146 138
 
147
-        BlueButton{
148
-            id:serverSearchButton
149
-            text:"\uf002"
150
-            x:19*mm
151
-            y:10*mm
152
-            width: 5*mm; height:5*mm
153
-            visible: servericon.visible?false:true
154
-            onClicked:{Qt.openUrlExternally(Qt.resolvedUrl("https://dir.friendica.social/servers"))}
139
+    Image{
140
+        id:servericon
141
+        x:4*mm;y:13.5*mm
142
+        width:5*mm; height: 5*mm
143
+        visible: false
144
+        source:""
145
+        MouseArea{
146
+            anchors.fill:parent
147
+            onClicked:{
148
+                Service.showServerConfig(servername.text, configBackground, function(configString){
149
+                var serverconfigObject=Qt.createQmlObject(configString,configBackground,"serverconfigOutput");})
150
+            }
155 151
         }
152
+    }
156 153
 
154
+    BlueButton{
155
+        id:serverSearchButton
156
+        text:"\uf002"
157
+        x:4*mm
158
+        y:13.5*mm
159
+        width: 5*mm; height:5*mm
160
+        visible: servericon.visible?false:true
161
+        onClicked:{Qt.openUrlExternally(Qt.resolvedUrl("https://dir.friendica.social/servers"))}
162
+    }
157 163
 
158
-        Rectangle{color: "light grey";  x: 25*mm; y: 10*mm; width: root.width/2; height: 5*mm;}
159
-         Flickable {
160
-         id: servernameFlickable
161
-         x: 25*mm; y: 10*mm; width: root.width/2; height: 5*mm;
162
-          contentWidth: servername.paintedWidth
163
-         contentHeight: servername.paintedHeight
164
-         clip: true
165
-         TextEdit {
166
-             id: servername
167
-             width: servernameFlickable.width
168
-             height: servernameFlickable.height
169
-             focus: true
170
-             text:"https://..."
171
-             onEditingFinished:{
164
+    Rectangle{color: "light grey";  x: 10*mm; y: 13.5*mm; width: root.width-12*mm; height: 5*mm;}
165
+    Flickable {
166
+        id: servernameFlickable
167
+        x: 10*mm; y: 13.5*mm; width: root.width-12*mm; height: 5*mm;
168
+        contentWidth: servername.paintedWidth
169
+        contentHeight: servername.paintedHeight
170
+        clip: true
171
+        TextEdit {
172
+            id: servername
173
+            width: servernameFlickable.width
174
+            height: servernameFlickable.height
175
+            focus: true
176
+            font.pixelSize:3*mm
177
+            text:"https://..."
178
+            onEditingFinished:{
172 179
                  if((servername.text).substring(0,14) =="https://...http"){
173 180
                      serverstring.text= (serverstring.text).substring(11)
174 181
                  }
175
-
176 182
                configBackground.setServericon(servername.text)
177 183
              }
178 184
             onCursorRectangleChanged: Layoutjs.ensureVisibility(cursorRectangle,servernameFlickable)
179
-         }
180
-     }
185
+        }
186
+    }
181 187
 
182
-     Rectangle{
183
-         color: "light grey"
184
-         x: 25*mm; y: 20*mm; width: root.width/2-9*mm; height: 5*mm;
185
-         TextInput {
186
-             id: username
187
-             anchors.fill: parent
188
-             selectByMouse: true
188
+    Rectangle{
189
+        color: "light grey"
190
+        x: 4*mm; y: 23.5*mm; width: root.width-14*mm; height: 5*mm;
191
+        TextInput {
192
+            id: username
193
+            anchors.fill: parent
194
+            font.pixelSize:3*mm
195
+            selectByMouse: true
189 196
             onEditingFinished:{
190 197
                 if (username.text.indexOf('@')>-1){
191 198
                     Helperjs.showMessage(qsTr("Error"),qsTr("Nicknames containing @ symbol currently not supported"),configBackground)
@@ -201,47 +208,71 @@ StackView{
201 208
             }
202 209
          }
203 210
     }
204
-     BlueButton {
205
-         x: root.width/2+18*mm; y: 20*mm; width:7*mm
206
-         text: "\uf234"
207
-         onClicked: {
208
-             configStack.push({item:"qrc:/qml/configqml/RegisterPage.qml",properties:{url:servername.text+"/register?nickname="+username.getText(0,username.length)}})
209
-         }
210
-     }
211
+    BlueButton {
212
+        x: root.width-9*mm; y: 23.5*mm; width:7*mm
213
+        text: "\uf234"
214
+        onClicked: {
215
+            configStack.push({item:"qrc:/qml/configqml/RegisterPage.qml",properties:{url:servername.text+"/register?nickname="+username.getText(0,username.length)}})
216
+        }
217
+    }
211 218
 
212 219
     Rectangle{
213 220
         color: "light grey"
214
-         x: 25*mm; y: 30*mm; width: root.width/2; height: 5*mm;
221
+         x: 4*mm; y: 33.5*mm; width: root.width-6*mm; height: 5*mm;
215 222
          TextInput {
216 223
              id: password
217 224
              anchors.fill: parent
225
+             font.pixelSize:3*mm
218 226
              selectByMouse: true
219 227
              echoMode: TextInput.PasswordEchoOnEdit
220 228
         }
221 229
     }
222 230
 
223
-    Rectangle{color: "light grey"; x: 25*mm; y: 40*mm; width: root.width/2-9*mm; height: 5*mm;}
231
+    Rectangle{color: "light grey"; x: 4*mm; y: 43.5*mm; width: root.width-14*mm; height: 5*mm;}
224 232
     Flickable {
225 233
          id: imagestoreFlickable
226
-          x: 25*mm; y: 40*mm; width: root.width/2-9*mm; height: 5*mm;
234
+         x: 4*mm; y: 43.5*mm; width: root.width-14*mm; height: 5*mm;
227 235
          clip: true
228 236
          TextInput {
229 237
              id: imagestore
230 238
              width: imagestoreFlickable.width
231 239
              height: imagestoreFlickable.height
240
+             font.pixelSize:3*mm
232 241
              wrapMode: TextEdit.NoWrap
233 242
              onCursorRectangleChanged: Layoutjs.ensureVisibility(cursorRectangle,imagestoreFlickable)
234 243
          }
235 244
      }
245
+
246
+    FileDialog {
247
+        id: imagestoreDialog
248
+        title: "Please choose a directory"
249
+        folder: shortcuts.pictures
250
+        selectFolder: true
251
+        onAccepted: {
252
+            var imagestoreString=imagestoreDialog.folder.toString();
253
+            imagestoreString=imagestoreString.replace(/^(file:\/{2})/,"")+"/"
254
+            imagestore.text=imagestoreString
255
+        }
256
+    }
257
+
258
+     BlueButton {
259
+            x: root.width-9*mm; y: 43.5*mm; width: 7*mm; height: 5*mm;
260
+            text: "..."
261
+            onClicked:
262
+         {imagestoreDialog.open()}
263
+     }
264
+
265
+
236 266
     Slider{ id: maxNews
237
-        x:34*mm; y: 50*mm;width: root.width/3;height:5*mm
267
+        x:19*mm; y: 53.5*mm;width: root.width/2;height:5*mm
238 268
         minimumValue: 0;maximumValue:2000; stepSize: 100
239 269
     }
240 270
 
241 271
 
242
-    Rectangle{color: "light grey"; x: 25*mm; y: 50*mm; width: 9*mm; height: 5*mm;
272
+    Rectangle{color: "light grey"; x: 4*mm; y: 53.5*mm; width: 9*mm; height: 5*mm;
243 273
         TextEdit{id:maxNewsText;
244 274
             anchors.fill: parent
275
+            font.pixelSize:3*mm
245 276
             verticalAlignment:TextEdit.AlignRight
246 277
             text:maxNews.value
247 278
             focus: true
@@ -250,60 +281,43 @@ StackView{
250 281
     }
251 282
 
252 283
     Rectangle{
253
-         x: 25*mm; y: 60*mm; width: root.width/2; height: 5*mm;
284
+         x: 4*mm; y: 63.5*mm; width: newsTypeField.contentWidth+2*mm; height: 5*mm;
254 285
          color:"light grey"
255 286
          Text{
256
-         id: newsTypeField
257
-         anchors.fill: parent
258
-         text:"Conversations"
287
+             id: newsTypeField
288
+             anchors.fill: parent
289
+             font.pixelSize:3*mm
290
+             text:"Conversations"
259 291
         }
260 292
         MouseArea{
261
-        anchors.fill:parent
262
-        onClicked:newstypemenu.popup()
293
+            anchors.fill:parent
294
+            onClicked:newstypemenu.popup()
263 295
         }
264 296
     }
265 297
     Slider{ id: messageIntervalSlider
266
-        visible: false
267
-        x:37*mm; y: 70*mm;width: root.width/3;height:5*mm
268
-        minimumValue: 0;maximumValue:24; stepSize: 0.5
298
+        x:22*mm; y: 73.5*mm;width: root.width/2;height:5*mm
299
+        minimumValue: 0;maximumValue:120; stepSize: 15
269 300
     }
270 301
     Rectangle{
271
-        visible:false
272
-         x: 25*mm; y: 70*mm; width: 9*mm; height: 5*mm;
302
+         x: 4*mm; y: 73.5*mm; width: 9*mm; height: 5*mm;
273 303
          TextEdit{
274
-         id: messageIntervalField
275
-         anchors.fill: parent
276
-         verticalAlignment:TextEdit.AlignRight
277
-         text:messageIntervalSlider.value
278
-         focus: true
279
-         selectByMouse: true
304
+             id: messageIntervalField
305
+             anchors.fill: parent
306
+             font.pixelSize:3*mm
307
+             verticalAlignment:TextEdit.AlignRight
308
+             text:messageIntervalSlider.value
309
+             focus: true
310
+             selectByMouse: true
280 311
         }
281 312
     }
282
-
283
-    FileDialog {
284
-        id: imagestoreDialog
285
-        title: "Please choose a directory"
286
-        folder: shortcuts.pictures
287
-        selectFolder: true
288
-        onAccepted: {
289
-            var imagestoreString=imagestoreDialog.folder.toString();
290
-            imagestoreString=imagestoreString.replace(/^(file:\/{2})/,"")+"/"
291
-            imagestore.text=imagestoreString
292
-        }
293
- }
294
-
295
-     BlueButton {
296
-            x: root.width/2+18*mm; y: 40*mm; width: 7*mm; height: 5*mm;
297
-            text: "..."
298
-            onClicked:
299
-         {imagestoreDialog.open()}
300
-     }
301
-
302
-
313
+    Text{x: 14*mm; y: 73.5*mm; width: 5*mm; height: 5*mm;
314
+        font.pixelSize:3*mm
315
+        text:qsTr("Min.")
316
+    }
303 317
 
304 318
 //    CheckBox{
305 319
 //        id:showwebsiteCheckbox
306
-//        x:35*mm;y:70*mm
320
+//        x:35*mm;y:80*mm
307 321
 //        onClicked:{
308 322
 //            if (checked==true){
309 323
 //                Service.updateglobaloptions(root.db,"showWebsiteForLinks","true")
@@ -314,11 +328,10 @@ StackView{
314 328
 //                root.globaloptions.showWebsiteForLinks="false"
315 329
 //            }
316 330
 //        }
317
-        
318 331
 //    }
319 332
 
320 333
     BlueButton {
321
-    x: 25*mm; y: 78*mm
334
+    x: 4*mm; y: 83.5*mm
322 335
     text: qsTr("Confirm")
323 336
     onClicked:{
324 337
          var userconfig={server: servername.text, username: username.text, password:Qt.btoa(password.text), imagestore:imagestore.text,maxnews:maxNewsText.text,interval:  messageIntervalField.text, newsViewType:newsTypeField.text};
@@ -352,7 +365,10 @@ StackView{
352 365
                          root.login=userconfig;
353 366
                          root.news=[];
354 367
                      },"isActive",0);
355
-                     Service.requestProfile(userconfig,db,root,function(nc){root.newContacts=nc})
368
+                     Service.requestProfile(userconfig,db,root,function(nc){root.newContacts=nc});
369
+                     if(osSettings.osType=="Android" && userconfig.timerInterval !=0){
370
+                             alarm.setAlarm(userconfig.timerInterval);
371
+                         }
356 372
                      Helperjs.showMessage(qsTr("Success"),qsTr("Name")+": "+credentials.name+"\nScreen Name: "+credentials.screen_name,root)
357 373
                  }
358 374
              });
@@ -382,7 +398,7 @@ StackView{
382 398
            imagestore.text="";
383 399
            maxNews.value=0;
384 400
            newsTypeField.text="Conversations";
385
-           messageIntervalSlider.value=0;
401
+           messageIntervalSlider.value=30;
386 402
            userButton.text=qsTr("User");
387 403
            Helperjs.readData(db,"config","",function(storedUsers){
388 404
              storedUsers.sort(function(obj1, obj2) {
@@ -405,7 +421,7 @@ StackView{
405 421
         imagestore.text=""
406 422
         maxNews.value=0
407 423
         newsTypeField.text="Conversations"
408
-        messageIntervalSlider.value=0
424
+        messageIntervalSlider.value=30
409 425
         userButton.text=qsTr("User")
410 426
        }
411 427
      }
@@ -449,12 +465,12 @@ StackView{
449 465
             if( obj.isActive==0){userButton.fontColor='black'} else {userButton.fontColor='grey'}},"isActive",0
450 466
             )
451 467
           })
452
-            //Service.readGlobaloptions(db,function(go){
468
+//            Service.readGlobaloptions(db,function(go){
453 469
 //                if (root.globaloptions.showWebsiteForLinks!="false"){showwebsiteCheckbox.checked=true}
454
-            //})
470
+//            })
455 471
   
456 472
           }
457
-      catch (e){
473
+      catch (e){print(e)
458 474
           Helperjs.friendicaWebRequest("https://dir.friendica.social/servers/surprise",configBackground,function(html){
459 475
               var bpos=html.indexOf("baseurl");
460 476
               var baseurl=html.substring(html.indexOf("http",bpos),html.indexOf('"',html.indexOf("http",bpos)));

+ 1
- 1
source-android/qml/configqml/InfoBox.qml View File

@@ -43,7 +43,7 @@ Rectangle{
43 43
         textFormat: Text.RichText
44 44
         width: parent.width
45 45
         wrapMode: Text.WrapAtWordBoundaryOrAnywhere
46
-        text: "<b>Friendiqa v0.3.4 </b><br>Licensed under GPL 3 with the exception of OpenSSL <br> "+
46
+        text: "<b>Friendiqa v0.4 </b><br>Licensed under GPL 3 with the exception of OpenSSL <br> "+
47 47
               "Profile <a href='https://freunde.ma-nic.de/profile/friendiqa'>https://freunde.ma-nic.de/profile/friendiqa</a><br>"+
48 48
               "Sourcecode: <a href='https://git.friendi.ca/LubuWest/Friendiqa'>https://git.friendi.ca/LubuWest/Friendiqa</a><br>"+
49 49
                "Most of C++ code by <a href='https://kirgroup.com/profile/fabrixxm'>Fabio</a><br>"+

+ 1
- 0
source-android/qml/configqml/OSSettingsAndroid.qml View File

@@ -36,6 +36,7 @@ QtObject{
36 36
     property int appHeight: Screen.desktopAvailableHeight
37 37
     property int backKey: Qt.Key_Back
38 38
     //property string attachImageDir:filesystem.cameraPath+"/"
39
+    property string osType: "Android"
39 40
     property string imagePickQml: "ImagePicker"
40 41
     property string imagePicker:'import QtQuick 2.0; import "qrc:/qml/genericqml";'+
41 42
                           imagePickQml+'{multiple : true;onReady: {attachImageURLs.push(imageUrl);'+

+ 1
- 0
source-android/qml/configqml/OSSettingsLinux.qml View File

@@ -34,6 +34,7 @@ QtObject{
34 34
     property real appWidth: 500 
35 35
     property real appHeight: 500
36 36
     property int backKey: Qt.Key_Escape
37
+    property string osType: "Android"
37 38
     //property string attachImageDir:filesystem.homePath+"/Pictures/"
38 39
     property string imagePickQml: "ImagePickerLinux"
39 40
 }

+ 4
- 2
source-android/qml/friendiqa.qml View File

@@ -194,8 +194,10 @@ TabView{
194 194
     Component.onCompleted: {
195 195
         Service.readGlobaloptions(db,function(go){globaloptions=go})
196 196
         //print(xhr.networktype);
197
-        if(osSettings.imagePickQml=="ImagePicker"){var component = Qt.createComponent("qrc:/qml/genericqml/IntentReceiver.qml");
198
-            var IntentReceiverQml = component.createObject(root)
197
+        if(osSettings.osType=="Android"){
198
+            var component = Qt.createComponent("qrc:/qml/genericqml/IntentReceiver.qml");
199
+            var IntentReceiverQml = component.createObject(root);
200
+
199 201
         }
200 202
     }
201 203
 }

+ 4
- 0
source-android/qml/genericqml/IntentReceiver.qml View File

@@ -38,6 +38,10 @@ Item {
38 38
 
39 39
     Component.onCompleted: {
40 40
         SystemDispatcher.setInitialized();
41
+        print("timer " + login.timerInterval)
42
+        if (login.timerInterval !=0){
43
+            alarm.setAlarm(login.timerInterval);
44
+        }
41 45
     }
42 46
 }
43 47
 

+ 19
- 4
source-android/qml/newsqml/NewsLink.qml View File

@@ -45,8 +45,23 @@ Rectangle{
45 45
 //    WebView {id:htmlview;
46 46
 //        anchors.fill: parent
47 47
 //    }
48
-    Component.onCompleted: //Helperjs.friendicaWebRequest(url,parent,function(html){
49
-        //print(html);
50
-        htmlview.text="Text <iframe src='"+url+"' width = '300px' height = '300px'>"
51
-    //})
48
+    Component.onCompleted:{
49
+
50
+//        Helperjs.friendicaWebRequest(url,parent,function(document){
51
+//            print(document);
52
+
53
+////            var metas = document.getElementsByTagName('meta'); //get all the meta tag elements
54
+////        //iterate through them
55
+////        for (i=0; i<metas.length; i++) {
56
+////           if (metas[i].getAttribute("name") == "keywords") {
57
+////             print(metas[i].getAttribute("content"));
58
+////           }
59
+////          else if (metas[i].getAttribute("name") == "description") {
60
+////             console.log(metas[i].getAttribute("content"));
61
+////           }
62
+////        }
63
+//        //print(html);
64
+//        htmlview.text=""
65
+//        })
66
+    }
52 67
 }

+ 29
- 0
source-android/qml/newsqml/NewsTab.qml View File

@@ -40,6 +40,8 @@ import "qrc:/js/helper.js" as Helperjs
40 40
 import "qrc:/js/service.js" as Service
41 41
 
42 42
 
43
+import AndroidNative 1.0
44
+
43 45
 Item {
44 46
     Connections{
45 47
         target:newstab
@@ -59,6 +61,25 @@ Item {
59 61
         }
60 62
     }
61 63
 
64
+//    Connections{
65
+//        target:xhr
66
+//        onError:{
67
+//            Helperjs.showMessage(qsTr("Network Error"),"API:\n" +login.server+api+"\n Return: \n"+data,root);
68
+//        }
69
+//        onSuccess:{
70
+//            if (api=="/api/statuses/friends_timeline"){
71
+//           // downloadNotice.text=downloadNotice.text+ "\n xhr finished "+Date.now();
72
+//            //Service.processNews(api,data);
73
+//                if(login.newsViewType=="Timeline"){
74
+//                    Newsjs.newsfromdb(db,login.username,function(dbnews){showNews(dbnews)})}
75
+//                else{Newsjs.chatsfromdb(db,login.username,function(dbnews){
76
+//                    showNews(dbnews);
77
+//                })}
78
+//            }
79
+//        }
80
+//    }
81
+
82
+
62 83
     Timer {id:replytimer; interval: 1000; running: false; repeat: false
63 84
         onTriggered: {
64 85
             if(newstab.newstabstatus=="Conversation"){
@@ -221,6 +242,14 @@ Item {
221 242
                         Service.updateView("Favorites")
222 243
                     }
223 244
                 }
245
+                QC2.Action {
246
+                    text: qsTr("Replies")
247
+                    onTriggered:{
248
+                        newsStack.updateMethodNews="refresh";
249
+                        newstab.newstabstatus="Replies";
250
+                        Service.updateView("Replies")
251
+                    }
252
+                }
224 253
                 QC2.Action {
225 254
                     text: qsTr("Public timeline")
226 255
                     onTriggered:{

+ 100
- 0
source-android/qml/newsqml/NewsYplayer.qml View File

@@ -0,0 +1,100 @@
1
+
2
+
3
+//  This file is part of Friendiqa
4
+//  https://git.friendi.ca/lubuwest/Friendiqa
5
+//  Copyright (C) 2017 Marco R. <thomasschmidt45@gmx.net>
6
+//
7
+//  This program is free software: you can redistribute it and/or modify
8
+//  it under the terms of the GNU General Public License as published by
9
+//  the Free Software Foundation, either version 3 of the License, or
10
+//  (at your option) any later version.
11
+//
12
+//  In addition, as a special exception, the copyright holders give
13
+//  permission to link the code of portions of this program with the
14
+//  OpenSSL library under certain conditions as described in each
15
+//  individual source file, and distribute linked combinations including
16
+//  the two.
17
+//
18
+//  You must obey the GNU General Public License in all respects for all
19
+//  of the code used other than OpenSSL. If you modify file(s) with this
20
+//  exception, you may extend this exception to your version of the
21
+//  file(s), but you are not obligated to do so. If you do not wish to do
22
+//  so, delete this exception statement from your version. If you delete
23
+//  this exception statement from all source files in the program, then
24
+//  also delete it here.
25
+//
26
+//  This program is distributed in the hope that it will be useful,
27
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
28
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
29
+//  GNU General Public License for more details.
30
+//
31
+//  You should have received a copy of the GNU General Public License
32
+//  along with this program.  If not, see <http://www.gnu.org/licenses/>.
33
+
34
+import QtQuick 2.8
35
+import "qrc:/js/helper.js" as Helperjs
36
+//import QtWebView 1.1
37
+
38
+Rectangle{
39
+    color:"transparent"
40
+    width:newscolumn.width;
41
+    height:newscolumn.width/4*3
42
+    property string url:""//htmlview.text
43
+    WebView {
44
+        id: webView
45
+        anchors.fill: parent
46
+        opacity: 0
47
+
48
+        url: "qrc:///content/player.html?" + currentVideo.vId
49
+
50
+        Behavior on opacity { NumberAnimation { duration: 200 } }
51
+
52
+        onLoadingChanged: {
53
+            switch (loadRequest.status)
54
+            {
55
+            case WebView.LoadSucceededStatus:
56
+                opacity = 1
57
+                return
58
+            case WebView.LoadStartedStatus:
59
+            case WebView.LoadStoppedStatus:
60
+                break
61
+            case WebView.LoadFailedStatus:
62
+                topInfo.text = "Failed to load the requested video"
63
+                break
64
+            }
65
+            opacity = 0
66
+        }
67
+        onTitleChanged: {
68
+            currentVideo.status = 1 * title
69
+            if (title == videoStatus.paused || title == videoStatus.ready)
70
+                panel.state = "list"
71
+            else if (title == videoStatus.playing)
72
+                panel.state = "hidden"
73
+        }
74
+    }
75
+    Text{id:htmlview
76
+        textFormat:Text.RichText
77
+    }
78
+//    WebView {id:htmlview;
79
+//        anchors.fill: parent
80
+//    }
81
+    Component.onCompleted:{
82
+
83
+//        Helperjs.friendicaWebRequest(url,parent,function(document){
84
+//            print(document);
85
+
86
+////            var metas = document.getElementsByTagName('meta'); //get all the meta tag elements
87
+////        //iterate through them
88
+////        for (i=0; i<metas.length; i++) {
89
+////           if (metas[i].getAttribute("name") == "keywords") {
90
+////             print(metas[i].getAttribute("content"));
91
+////           }
92
+////          else if (metas[i].getAttribute("name") == "description") {
93
+////             console.log(metas[i].getAttribute("content"));
94
+////           }
95
+////        }
96
+//        //print(html);
97
+//        htmlview.text=""
98
+//        })
99
+    }
100
+}

+ 4
- 12
source-android/qml/newsqml/Newsitem.qml View File

@@ -184,10 +184,10 @@ Item {
184 184
                             var component = Qt.createComponent("qrc:/qml/newsqml/NewsImage.qml");
185 185
                             var imageQml = component.createObject(messageColumn,{"source":newsitemobject.attachmentList[attachments].url,"mimetype":newsitemobject.attachmentList[attachments].mimetype});
186 186
                         }
187
-//                        else if(newsitemobject.attachmentList[attachments].mimetype=="text/html"){
188
-//                            var component = Qt.createComponent("qrc:/qml/newsqml/NewsLink.qml");
189
-//                            var linkQml = component.createObject(messageColumn,{"url":newsitemobject.attachmentList[attachments].url});
190
-//                        }
187
+                        else if(newsitemobject.attachmentList[attachments].mimetype=="text/html"){
188
+                            var component = Qt.createComponent("qrc:/qml/newsqml/NewsLink.qml");
189
+                            var linkQml = component.createObject(messageColumn,{"url":newsitemobject.attachmentList[attachments].url});
190
+                        }
191 191
                         else {//print(newsitemobject.attachmentList[attachments].url+" Type: "+newsitemobject.attachmentList[attachments].mimetype)
192 192
                             var component = Qt.createComponent("qrc:/qml/newsqml/NewsVideo.qml");
193 193
                             var videoQml = component.createObject(messageColumn,{"source":newsitemobject.attachmentList[attachments].url,"mimetype":newsitemobject.attachmentList[attachments].mimetype});
@@ -461,14 +461,6 @@ Item {
461 461
                 })
462 462
             }
463 463
         }
464
-        MenuItem {
465
-            text: qsTr("Post")
466
-            onTriggered: {
467
-                Helperjs.friendicaPostRequest(root.login,"/item","preview=1&"+encodeURIComponent(newsitemobject.text),"POST",root,function(reply){
468
-                   print(reply)
469
-                })
470
-            }
471
-        }
472 464
 
473 465
         //MenuItem{
474 466
         //    text:qsTr("Show on website")

BIN
source-android/translations/friendiqa-de.qm View File


+ 103
- 78
source-android/translations/friendiqa-de.ts View File

@@ -18,8 +18,8 @@
18 18
     <name>ConfigTab</name>
19 19
     <message>
20 20
         <location filename="../qml/configqml/ConfigTab.qml" line="69"/>
21
-        <location filename="../qml/configqml/ConfigTab.qml" line="351"/>
22
-        <location filename="../qml/configqml/ConfigTab.qml" line="374"/>
21
+        <location filename="../qml/configqml/ConfigTab.qml" line="402"/>
22
+        <location filename="../qml/configqml/ConfigTab.qml" line="425"/>
23 23
         <source>User</source>
24 24
         <translation>Name</translation>
25 25
     </message>
@@ -29,38 +29,38 @@
29 29
         <translation>Server</translation>
30 30
     </message>
31 31
     <message>
32
-        <location filename="../qml/configqml/ConfigTab.qml" line="100"/>
32
+        <location filename="../qml/configqml/ConfigTab.qml" line="101"/>
33 33
         <source>Nickname</source>
34 34
         <translation>Kurzname</translation>
35 35
     </message>
36 36
     <message>
37
-        <location filename="../qml/configqml/ConfigTab.qml" line="105"/>
37
+        <location filename="../qml/configqml/ConfigTab.qml" line="107"/>
38 38
         <source>Password</source>
39 39
         <translation>Passwort</translation>
40 40
     </message>
41 41
     <message>
42
-        <location filename="../qml/configqml/ConfigTab.qml" line="109"/>
42
+        <location filename="../qml/configqml/ConfigTab.qml" line="112"/>
43 43
         <source>Image dir.</source>
44 44
         <translation>Bildverz.</translation>
45 45
     </message>
46 46
     <message>
47
-        <location filename="../qml/configqml/ConfigTab.qml" line="114"/>
47
+        <location filename="../qml/configqml/ConfigTab.qml" line="118"/>
48 48
         <source>Max. News</source>
49 49
         <translation>Max. Nachr.</translation>
50 50
     </message>
51 51
     <message>
52
-        <location filename="../qml/configqml/ConfigTab.qml" line="118"/>
52
+        <location filename="../qml/configqml/ConfigTab.qml" line="123"/>
53 53
         <source>News as</source>
54 54
         <translation>Anzeige</translation>
55 55
     </message>
56 56
     <message>
57
-        <location filename="../qml/configqml/ConfigTab.qml" line="122"/>
58 57
         <source>Interval (0=None)</source>
59
-        <translation>Intervall (0=keins)</translation>
58
+        <translation type="vanished">Intervall (0=keins)</translation>
60 59
     </message>
61 60
     <message>
62
-        <location filename="../qml/configqml/ConfigTab.qml" line="304"/>
63
-        <location filename="../qml/configqml/ConfigTab.qml" line="328"/>
61
+        <location filename="../qml/configqml/ConfigTab.qml" line="198"/>
62
+        <location filename="../qml/configqml/ConfigTab.qml" line="350"/>
63
+        <location filename="../qml/configqml/ConfigTab.qml" line="377"/>
64 64
         <source>Error</source>
65 65
         <translation>Fehler</translation>
66 66
     </message>
@@ -69,22 +69,22 @@
69 69
         <translation type="vanished">Name auf der Seite nicht registriert!</translation>
70 70
     </message>
71 71
     <message>
72
-        <location filename="../qml/configqml/ConfigTab.qml" line="289"/>
72
+        <location filename="../qml/configqml/ConfigTab.qml" line="335"/>
73 73
         <source>Confirm</source>
74 74
         <translation>Bestätigen</translation>
75 75
     </message>
76 76
     <message>
77
-        <location filename="../qml/configqml/ConfigTab.qml" line="293"/>
77
+        <location filename="../qml/configqml/ConfigTab.qml" line="339"/>
78 78
         <source>No server given! </source>
79 79
         <translation>Kein Server angegeben!</translation>
80 80
     </message>
81 81
     <message>
82
-        <location filename="../qml/configqml/ConfigTab.qml" line="294"/>
82
+        <location filename="../qml/configqml/ConfigTab.qml" line="340"/>
83 83
         <source>No nickname given! </source>
84 84
         <translation>Kein Kurzname angegeben!</translation>
85 85
     </message>
86 86
     <message>
87
-        <location filename="../qml/configqml/ConfigTab.qml" line="295"/>
87
+        <location filename="../qml/configqml/ConfigTab.qml" line="341"/>
88 88
         <source>Nickname not registered at given server! </source>
89 89
         <translation>Name auf der Seite nicht registriert!</translation>
90 90
     </message>
@@ -93,42 +93,57 @@
93 93
         <translation type="vanished">Kein Nutzername angegeben!</translation>
94 94
     </message>
95 95
     <message>
96
-        <location filename="../qml/configqml/ConfigTab.qml" line="296"/>
96
+        <location filename="../qml/configqml/ConfigTab.qml" line="128"/>
97
+        <source>Sync Interval (0=None)</source>
98
+        <translation>Akt.-intervall (0=keine)</translation>
99
+    </message>
100
+    <message>
101
+        <location filename="../qml/configqml/ConfigTab.qml" line="198"/>
102
+        <source>Nicknames containing @ symbol currently not supported</source>
103
+        <translation>Kurznamen mit @ Zeichen werden derzeit nicht unterstützt.</translation>
104
+    </message>
105
+    <message>
106
+        <location filename="../qml/configqml/ConfigTab.qml" line="315"/>
107
+        <source>Min.</source>
108
+        <translation>Min.</translation>
109
+    </message>
110
+    <message>
111
+        <location filename="../qml/configqml/ConfigTab.qml" line="342"/>
97 112
         <source>No password given! </source>
98 113
         <translation>Kein Passwort angegeben!</translation>
99 114
     </message>
100 115
     <message>
101
-        <location filename="../qml/configqml/ConfigTab.qml" line="297"/>
116
+        <location filename="../qml/configqml/ConfigTab.qml" line="343"/>
102 117
         <source>No image directory given!</source>
103 118
         <translation>Kein Verzeichnis für Bilder angegeben!</translation>
104 119
     </message>
105 120
     <message>
106
-        <location filename="../qml/configqml/ConfigTab.qml" line="298"/>
121
+        <location filename="../qml/configqml/ConfigTab.qml" line="344"/>
107 122
         <source>No maximum news number given!</source>
108 123
         <translation>Maximale News-Anzahl nicht angegeben!</translation>
109 124
     </message>
110 125
     <message>
111
-        <location filename="../qml/configqml/ConfigTab.qml" line="304"/>
126
+        <location filename="../qml/configqml/ConfigTab.qml" line="350"/>
112 127
         <source>Wrong password!</source>
113 128
         <translation>Falsches Passwort!</translation>
114 129
     </message>
115 130
     <message>
116
-        <location filename="../qml/configqml/ConfigTab.qml" line="323"/>
131
+        <location filename="../qml/configqml/ConfigTab.qml" line="372"/>
117 132
         <source>Success</source>
118 133
         <translation>Bestätigt</translation>
119 134
     </message>
120 135
     <message>
121
-        <location filename="../qml/configqml/ConfigTab.qml" line="323"/>
136
+        <location filename="../qml/configqml/ConfigTab.qml" line="372"/>
122 137
         <source>Name</source>
123 138
         <translation>Name</translation>
124 139
     </message>
125 140
     <message>
126
-        <location filename="../qml/configqml/ConfigTab.qml" line="389"/>
141
+        <location filename="../qml/configqml/ConfigTab.qml" line="440"/>
127 142
         <source>Timeline</source>
128 143
         <translation>Chronologisch</translation>
129 144
     </message>
130 145
     <message>
131
-        <location filename="../qml/configqml/ConfigTab.qml" line="393"/>
146
+        <location filename="../qml/configqml/ConfigTab.qml" line="444"/>
132 147
         <source>Conversations</source>
133 148
         <translation>Unterhaltungen</translation>
134 149
     </message>
@@ -182,27 +197,27 @@
182 197
         <translation>Kontaktanfrage</translation>
183 198
     </message>
184 199
     <message>
185
-        <location filename="../qml/newsqml/ContactPage.qml" line="152"/>
200
+        <location filename="../qml/newsqml/ContactPage.qml" line="151"/>
186 201
         <source>Description</source>
187 202
         <translation>Beschreibung</translation>
188 203
     </message>
189 204
     <message>
190
-        <location filename="../qml/newsqml/ContactPage.qml" line="152"/>
205
+        <location filename="../qml/newsqml/ContactPage.qml" line="151"/>
191 206
         <source>Location</source>
192 207
         <translation>Ort</translation>
193 208
     </message>
194 209
     <message>
195
-        <location filename="../qml/newsqml/ContactPage.qml" line="152"/>
210
+        <location filename="../qml/newsqml/ContactPage.qml" line="151"/>
196 211
         <source>Posts</source>
197 212
         <translation>Beiträge</translation>
198 213
     </message>
199 214
     <message>
200
-        <location filename="../qml/newsqml/ContactPage.qml" line="153"/>
215
+        <location filename="../qml/newsqml/ContactPage.qml" line="152"/>
201 216
         <source>URL</source>
202 217
         <translation>Profilseite</translation>
203 218
     </message>
204 219
     <message>
205
-        <location filename="../qml/newsqml/ContactPage.qml" line="154"/>
220
+        <location filename="../qml/newsqml/ContactPage.qml" line="153"/>
206 221
         <source>Created at</source>
207 222
         <translation>Erstellt</translation>
208 223
     </message>
@@ -309,12 +324,12 @@
309 324
         <translation type="vanished">Lade Profilbild für </translation>
310 325
     </message>
311 326
     <message>
312
-        <location filename="../qml/newsqml/NewsTab.qml" line="330"/>
327
+        <location filename="../qml/newsqml/NewsTab.qml" line="359"/>
313 328
         <source>More</source>
314 329
         <translation>Mehr</translation>
315 330
     </message>
316 331
     <message>
317
-        <location filename="../qml/newsqml/NewsTab.qml" line="200"/>
332
+        <location filename="../qml/newsqml/NewsTab.qml" line="221"/>
318 333
         <source>Timeline</source>
319 334
         <translation>Chronologisch</translation>
320 335
     </message>
@@ -323,42 +338,47 @@
323 338
         <translation type="vanished">Fehler</translation>
324 339
     </message>
325 340
     <message>
326
-        <location filename="../qml/newsqml/NewsTab.qml" line="217"/>
341
+        <location filename="../qml/newsqml/NewsTab.qml" line="238"/>
327 342
         <source>Favorites</source>
328 343
         <translation>Markierte News</translation>
329 344
     </message>
330 345
     <message>
331
-        <location filename="../qml/newsqml/NewsTab.qml" line="209"/>
346
+        <location filename="../qml/newsqml/NewsTab.qml" line="230"/>
332 347
         <source>Conversations</source>
333 348
         <translation>Unterhaltungen</translation>
334 349
     </message>
335 350
     <message>
336
-        <location filename="../qml/newsqml/NewsTab.qml" line="54"/>
351
+        <location filename="../qml/newsqml/NewsTab.qml" line="56"/>
337 352
         <source>Network Error</source>
338 353
         <translation>Netzwerk-Fehler</translation>
339 354
     </message>
340 355
     <message>
341
-        <location filename="../qml/newsqml/NewsTab.qml" line="225"/>
356
+        <location filename="../qml/newsqml/NewsTab.qml" line="246"/>
357
+        <source>Replies</source>
358
+        <translation>Interaktionen</translation>
359
+    </message>
360
+    <message>
361
+        <location filename="../qml/newsqml/NewsTab.qml" line="254"/>
342 362
         <source>Public timeline</source>
343 363
         <translation>Gemeinschaft</translation>
344 364
     </message>
345 365
     <message>
346
-        <location filename="../qml/newsqml/NewsTab.qml" line="234"/>
366
+        <location filename="../qml/newsqml/NewsTab.qml" line="263"/>
347 367
         <source>Direct Messages</source>
348 368
         <translation>Direktnachrichten</translation>
349 369
     </message>
350 370
     <message>
351
-        <location filename="../qml/newsqml/NewsTab.qml" line="242"/>
371
+        <location filename="../qml/newsqml/NewsTab.qml" line="271"/>
352 372
         <source>Notifications</source>
353 373
         <translation>Meldungen</translation>
354 374
     </message>
355 375
     <message>
356
-        <location filename="../qml/newsqml/NewsTab.qml" line="251"/>
376
+        <location filename="../qml/newsqml/NewsTab.qml" line="280"/>
357 377
         <source>Group news</source>
358 378
         <translation>News Gruppe</translation>
359 379
     </message>
360 380
     <message>
361
-        <location filename="../qml/newsqml/NewsTab.qml" line="259"/>
381
+        <location filename="../qml/newsqml/NewsTab.qml" line="288"/>
362 382
         <source>Quit</source>
363 383
         <translation>Schliessen</translation>
364 384
     </message>
@@ -391,60 +411,65 @@
391 411
         <translation> Kommentare</translation>
392 412
     </message>
393 413
     <message>
394
-        <location filename="../qml/newsqml/Newsitem.qml" line="281"/>
414
+        <location filename="../qml/newsqml/Newsitem.qml" line="283"/>
395 415
         <source>Attending: </source>
396 416
         <translation>Teilnahme: </translation>
397 417
     </message>
398 418
     <message>
399
-        <location filename="../qml/newsqml/Newsitem.qml" line="403"/>
419
+        <location filename="../qml/newsqml/Newsitem.qml" line="405"/>
400 420
         <source>Reply</source>
401 421
         <translation>Antworten</translation>
402 422
     </message>
403 423
     <message>
404
-        <location filename="../qml/newsqml/Newsitem.qml" line="411"/>
424
+        <location filename="../qml/newsqml/Newsitem.qml" line="413"/>
405 425
         <source>DM</source>
406 426
         <translation>Direktnachricht</translation>
407 427
     </message>
408 428
     <message>
409
-        <location filename="../qml/newsqml/Newsitem.qml" line="417"/>
429
+        <location filename="../qml/newsqml/Newsitem.qml" line="419"/>
410 430
         <source>Repost</source>
411 431
         <translation>Teilen</translation>
412 432
     </message>
413 433
     <message>
414
-        <location filename="../qml/newsqml/Newsitem.qml" line="420"/>
434
+        <location filename="../qml/newsqml/Newsitem.qml" line="422"/>
415 435
         <source>Success!</source>
416 436
         <translation>Erledigt!</translation>
417 437
     </message>
418 438
     <message>
419
-        <location filename="../qml/newsqml/Newsitem.qml" line="425"/>
439
+        <location filename="../qml/newsqml/Newsitem.qml" line="427"/>
420 440
         <source>Conversation</source>
421 441
         <translation>Unterhaltung</translation>
422 442
     </message>
423 443
     <message>
424
-        <location filename="../qml/newsqml/Newsitem.qml" line="435"/>
444
+        <location filename="../qml/newsqml/Newsitem.qml" line="437"/>
425 445
         <source>Attending</source>
426 446
         <translation>Teilnahme</translation>
427 447
     </message>
428 448
     <message>
429
-        <location filename="../qml/newsqml/Newsitem.qml" line="437"/>
449
+        <location filename="../qml/newsqml/Newsitem.qml" line="439"/>
430 450
         <source>yes</source>
431 451
         <translation>ja</translation>
432