Browse Source

v.0.4

tags/v0.5
LubuWest 1 year 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 @@

## v0.3.2 ##
* For news containing url ending with mp3, mp4, avi, webm, ogg: media can be played in app
* Pictures can be renamed or moved to another album
* Bugfix: random crashes for conversations
* Bugfix: attach image to message works again
* Bugfix: check for nickname on Server has been removed due to API change
* Pictures can be renamed or moved to another album
* Bugfix: random crashes for conversations
* Bugfix: attach image to message works again
* Bugfix: check for nickname on Server has been removed due to API change


## v0.3.3 ##
* Update for OpenSSL and At
* Experimental support for Peertube (links are expanded to video widget)
* Some Unicode emojis
* Redesign of contact details (click on contact opens in new stack and shows last news)

* Update for OpenSSL and At
* Experimental support for Peertube (links are expanded to video widget)
* Some Unicode emojis
* Redesign of contact details (click on contact opens in new stack and shows last news)

## v0.3.4 ##
* Direct message creation from profile page works again
* Profile image upload works again
* Viewing private album pictures of contacts works again
* On first start servername from https://dir.friendica.social/servers/surprise selected
* Register button opens webview of registration page on server

* Direct message creation from profile page works again
* Profile image upload works again
* Viewing private album pictures of contacts works again
* On first start servername from https://dir.friendica.social/servers/surprise selected
* Register button opens webview of registration page on server

## v0.4 ##
* Background sync for friends timeline (interval on config page must be > 0) for Android > 5
* Replies timeline
* 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.
# News #
Currently supported:
* Shows Posts from friends, selected group, favorited messages, public timeline, Direct Messages and notifications
* Shows Posts from friends, selected group, replies, favorited messages, public timeline, Direct Messages and notifications
* Background sync with configurable interval of 15 min to 2h for active contact for friends timeline (Android 5 required)
* Search button for news
* Click on hashtag in newsitem starts search for news with that word
* Click on image shows image fullscreen


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

@@ -1,5 +1,5 @@
<?xml version="1.0"?>
<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">
<manifest package="org.qtproject.friendiqa" xmlns:android="http://schemas.android.com/apk/res/android" android:versionName="0.4" android:versionCode="12" android:installLocation="auto">
<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">
<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="">
<intent-filter>
@@ -49,6 +49,42 @@
<meta-data android:name="android.app.background_running" android:value="false"/>
<!-- Background running -->
</activity>

<service android:name="androidnative.friendiqa.FriendiqaService" android:permission="android.permission.BIND_JOB_SERVICE">
<meta-data android:name="android.app.background_running" android:value="true"/>
</service>
<service android:process=":qt" android:name="androidnative.AndroidNativeService">
<meta-data android:name="android.app.background_running" android:value="true"/>
<meta-data android:name="android.app.arguments" android:value="-service"/>
<meta-data android:name="android.app.lib_name" android:value="friendiqa"/>
<meta-data android:name="android.app.qt_sources_resource_id" android:resource="@array/qt_sources"/>
<meta-data android:name="android.app.repository" android:value="default"/>
<meta-data android:name="android.app.qt_libs_resource_id" android:resource="@array/qt_libs"/>
<meta-data android:name="android.app.bundled_libs_resource_id" android:resource="@array/bundled_libs"/>
<!-- Deploy Qt libs as part of package -->
<meta-data android:name="android.app.bundle_local_qt_libs" android:value="-- %%BUNDLE_LOCAL_QT_LIBS%% --"/>
<meta-data android:name="android.app.bundled_in_lib_resource_id" android:resource="@array/bundled_in_lib"/>
<meta-data android:name="android.app.bundled_in_assets_resource_id" android:resource="@array/bundled_in_assets"/>
<!-- Run with local libs -->
<meta-data android:name="android.app.use_local_qt_libs" android:value="-- %%USE_LOCAL_QT_LIBS%% --"/>
<meta-data android:name="android.app.libs_prefix" android:value="/data/local/tmp/qt/"/>
<meta-data android:name="android.app.load_local_libs" android:value="-- %%INSERT_LOCAL_LIBS%% --"/>
<meta-data android:name="android.app.load_local_jars" android:value="-- %%INSERT_LOCAL_JARS%% --"/>
<meta-data android:name="android.app.static_init_classes" android:value="-- %%INSERT_INIT_CLASSES%% --"/>
<!-- Messages maps -->
<meta-data android:value="@string/ministro_not_found_msg" android:name="android.app.ministro_not_found_msg"/>
<meta-data android:value="@string/ministro_needed_msg" android:name="android.app.ministro_needed_msg"/>
<meta-data android:value="@string/fatal_error_msg" android:name="android.app.fatal_error_msg"/>
<!-- Messages maps -->
<meta-data android:name="android.app.splash_screen_drawable" android:resource="@drawable/splash"/>
</service>
<service android:process=":qt" android:name="androidnative.friendiqa.FriendiqaStopService" android:permission="android.permission.BIND_JOB_SERVICE"
android:exported="true">
<meta-data android:name="android.app.background_running" android:value="true"/>
</service>
</application>
<uses-sdk android:minSdkVersion="18" android:targetSdkVersion="26"/>
<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 {
compile fileTree(dir: 'libs', include: ['*.jar'])
}

//apply plugin: 'android-library'

dependencies {
compile 'com.android.support:support-v4:25.3.1'
}


android {
/*******************************************************
* The following variables:
@@ -56,4 +63,4 @@ android {
}
}
apply from: "androidnative.gradle"
setAndroidNativePath("/../androidnative.pri");
setAndroidNativePath("/../androidnative.pri");

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

@@ -2,10 +2,6 @@ package androidnative.friendiqa;

import androidnative.AndroidNativeActivity;





public class FriendiqaActivity extends AndroidNativeActivity {
public FriendiqaActivity() {
super();
@@ -13,8 +9,4 @@ public class FriendiqaActivity extends AndroidNativeActivity {
QT_ANDROID_THEMES = new String[] {""};
QT_ANDROID_DEFAULT_THEME = "";
}




}

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

@@ -0,0 +1,96 @@
package androidnative.friendiqa;
import androidnative.SystemDispatcher;
import android.app.Notification;
import android.app.NotificationManager;
import android.util.Log;
import android.os.Handler;
import android.app.Activity;
import android.view.View;
import android.content.Context;
import java.util.Map;
import org.qtproject.qt5.android.QtNative;

public class FriendiqaNotifierService {

static {

SystemDispatcher.addListener(new SystemDispatcher.Listener() {

NotificationManager m_notificationManager;
Notification.Builder m_builder;

private void notificationManagerNotify(Map data) {

final Activity activity = QtNative.activity();
final Map messageData = data;

Runnable runnable = new Runnable () {
public void run() {
try {
String title = (String) messageData.get("title");

String message = (String) messageData.get("message");

if (m_notificationManager == null) {
m_notificationManager = (NotificationManager) activity.getSystemService(Context.NOTIFICATION_SERVICE);
m_builder = new Notification.Builder(activity);

// Small Icon is a must to make notification works.
// And that is why you need to inherit QtActivity
//m_builder.setSmallIcon(drawable.icon);
}

m_builder.setContentTitle(title);
m_builder.setContentText(message);
m_notificationManager.notify(1, m_builder.build());

// Test function. Remove it later.
SystemDispatcher.dispatch("Notifier.notifyFinished");
} catch (Exception e) {
Log.d("",e.getMessage());
}

};
};
activity.runOnUiThread(runnable);
}

private void hapticFeedbackPerform(Map data) {

final Activity activity = QtNative.activity();
final Map messageData = data;
Runnable runnable = new Runnable () {
public void run() {
int feedbackConstant = (Integer) messageData.get("feedbackConstant");
int flags = (Integer) messageData.get("flags");

Log.d("",String.format("hapticFeedbackPerform(%d,%d)",feedbackConstant,flags));

View rootView = activity.getWindow().getDecorView().getRootView();
rootView.performHapticFeedback(feedbackConstant, flags);

// Test function. Remove it later.
SystemDispatcher.dispatch("hapticFeedbackPerformFinished");
};
};
activity.runOnUiThread(runnable);
}

public void onDispatched(String name , Map data) {

if (name.equals("Notifier.notify")) {
notificationManagerNotify(data);
return;
} else if (name.equals("hapticFeedbackPerform")) {
hapticFeedbackPerform(data);
return;
}

return;
}
});

}

}


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

@@ -0,0 +1,35 @@
package androidnative.friendiqa;
import android.content.Context;
import android.content.Intent;
import android.util.Log;
import android.app.job.JobService;
import android.app.job.JobParameters;
import androidnative.AndroidNativeService;
import org.qtproject.qt5.android.bindings.QtService;
import org.qtproject.qt5.android.QtNative;
//import androidnative.friendiqa.FriendiqaQtService;

public class FriendiqaService extends JobService{
private static String TAG = "AndroidNative";
//Log.e(TAG,"Service");


@Override
public boolean onStartJob(JobParameters params) {
//Log.d(TAG,"Friendiqa JobService");
Context context = this.getApplicationContext();
AndroidNativeService fs = new AndroidNativeService();
fs.startQtService(context);
jobFinished(params,false);
//Intent serviceIntent = new Intent(this, AndroidNativeService.class);
//startService(serviceIntent);
return false;
}

@Override
public boolean onStopJob(JobParameters params) {
// whether or not you would like JobScheduler to automatically retry your failed job.
return false;
}
}


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

@@ -0,0 +1,40 @@
package androidnative.friendiqa;
import android.content.Context;
import android.content.Intent;
import android.util.Log;
import android.app.job.JobService;
import android.app.job.JobParameters;
import androidnative.AndroidNativeService;
import org.qtproject.qt5.android.bindings.QtService;
import org.qtproject.qt5.android.QtNative;
//import androidnative.friendiqa.FriendiqaQtService;

public class FriendiqaStopService extends JobService{
private static String TAG = "AndroidNative";
//Log.e(TAG,"Service");


@Override
public boolean onStartJob(JobParameters params) {
//Log.d(TAG,"Friendiqa JobServiceStop");
Context context = this.getApplicationContext();
AndroidNativeService fs = new AndroidNativeService();
fs.stopQtService(context);
jobFinished(params,false);
//Intent serviceIntent = new Intent(this, AndroidNativeService.class);
//startService(serviceIntent);
return false;
}

@Override
public boolean onStopJob(JobParameters params) {
// whether or not you would like JobScheduler to automatically retry your failed job.
return true;
}
@Override
public boolean onUnbind(Intent intent) {
stopSelf();
return super.onUnbind(intent);
}

}

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

@@ -4,6 +4,11 @@ import android.util.Log;
import android.app.Activity;
import android.os.*;
import java.util.Map;
import android.content.pm.PackageManager;
import android.content.Context;
import android.Manifest.permission;
import android.support.v4.app.ActivityCompat;
import android.support.v4.content.ContextCompat;

/** An alternative Activity class for Qt applicaiton.

@@ -11,6 +16,8 @@ import java.util.Map;
*/

public class AndroidNativeActivity extends org.qtproject.qt5.android.bindings.QtActivity {
public static final int MY_PERMISSIONS_REQUEST_WRITE_STORAGE = 0x245285a8;


@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
@@ -21,6 +28,17 @@ public class AndroidNativeActivity extends org.qtproject.qt5.android.bindings.Qt

protected void onResume() {
super.onResume();
if (ContextCompat.checkSelfPermission(this,android.Manifest.permission.WRITE_EXTERNAL_STORAGE)!= PackageManager.PERMISSION_GRANTED) {

// Permission is not granted

ActivityCompat.requestPermissions(this,new String[]{android.Manifest.permission.WRITE_EXTERNAL_STORAGE},MY_PERMISSIONS_REQUEST_WRITE_STORAGE);

// MY_PERMISSIONS_REQUEST_READ_CONTACTS is an
// app-defined int constant. The callback method gets the
// result of the request.
} else {

System.loadLibrary("friendiqa");
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))) {
SystemDispatcher.onActivityResume();
@@ -48,6 +66,25 @@ public class AndroidNativeActivity extends org.qtproject.qt5.android.bindings.Qt
SystemDispatcher.onActivityResume();
}}
}
}




@Override public void onRequestPermissionsResult(int requestCode,String permissions[], int[] grantResults) {
switch (requestCode) {
case MY_PERMISSIONS_REQUEST_WRITE_STORAGE: {
// If request is cancelled, the result arrays are empty.
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
SystemDispatcher.onActivityResume();
} else {
}
return;
}
}
}



protected void onNewIntent(Intent data) {
System.loadLibrary("friendiqa");


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

@@ -0,0 +1,23 @@
package androidnative;
import android.content.Context;
import android.content.Intent;
import android.util.Log;
import org.qtproject.qt5.android.bindings.QtService;
public class AndroidNativeService extends QtService
{
private static String TAG = "AndroidNative";
public void startQtService(Context ctx) {
Log.d(TAG,"Friendiqa QtService");
ctx.startService(new Intent(ctx, AndroidNativeService.class));
}
public static void stopQtService(Context ctx) {
Log.d(TAG,"Friendiqa QtServiceStop");

ctx.stopService(new Intent(ctx, AndroidNativeService.class));
}
}

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

@@ -6,9 +6,15 @@ import android.util.Log;
import android.view.View;
import android.view.Window;
import android.view.WindowManager;

import android.content.Context;
import android.content.ComponentName;
import android.app.job.JobScheduler;
import android.app.job.JobInfo;
import org.qtproject.qt5.android.QtNative;

import androidnative.friendiqa.FriendiqaService;
import androidnative.friendiqa.FriendiqaStopService;
import androidnative.AndroidNativeService;
import android.content.Intent;
import java.util.Map;

public class Util {
@@ -17,6 +23,7 @@ public class Util {

public static final String SET_TRANSLUCENT_STATUS_BAR = "androidnative.Util.setTranslucentStatusBar";
public static final String SET_FULL_SCREEN = "androidnative.Util.setFullScreen";
public static final String SET_SCHEDULE = "androidnative.Util.setSchedule";


static {
@@ -26,6 +33,8 @@ public class Util {
setTranslucentStatusBar(message);
} else if (type.equals(SET_FULL_SCREEN)) {
setFullScreen(message);
} else if (type.equals(SET_SCHEDULE)) {
setSchedule(message);
}
}
});
@@ -62,6 +71,10 @@ public class Util {
return;
}

if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
return;
}

final Boolean value = (Boolean) message.get("value");
final Activity activity = QtNative.activity();

@@ -84,4 +97,52 @@ public class Util {
activity.runOnUiThread(runnable);

}

static void setSchedule(Map message) {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
return;
}
Log.d(TAG,"Friendiqa schedule Androidnative service");
final Integer value = (Integer) message.get("value");
//final Activity activity = QtNative.activity();
//final Service service = QtNative.service();
//final int JOB_ID = 1;
final int ONE_MIN = 60 * 1000;
Context context;
if (QtNative.activity() == null){
context = QtNative.service().getApplicationContext();
} else {
context = QtNative.activity().getApplicationContext();
}
ComponentName component = new ComponentName(context, FriendiqaService.class);
JobInfo.Builder builder = new JobInfo.Builder(2, component)
// schedule it to run any time between 1 - 5 minutes
.setMinimumLatency(value * ONE_MIN)
.setOverrideDeadline((value + 5)*ONE_MIN)
//.setPeriodic(value * ONE_MIN)
.setRequiredNetworkType(JobInfo.NETWORK_TYPE_ANY);
JobScheduler jobScheduler = (JobScheduler) context.getSystemService(Context.JOB_SCHEDULER_SERVICE);
jobScheduler.schedule(builder.build());
if (QtNative.service() != null){
Log.d(TAG,"Schedule Stopping Friendiqa Androidnative service");
ComponentName componentStopper = new ComponentName(context, FriendiqaStopService.class);
JobInfo.Builder stopbuilder = new JobInfo.Builder(1, componentStopper)
.setMinimumLatency(50)
.setOverrideDeadline(100);
JobScheduler jobStopScheduler = (JobScheduler) context.getSystemService(Context.JOB_SCHEDULER_SERVICE);
jobStopScheduler.schedule(stopbuilder.build());
//AndroidNativeService.stopQtService(context);
}
//context.stopService(new Intent(context, AndroidNativeService.class));
}

/**static void stopService(Map message){
this.stopService(new Intent(this, AndroidNativeService.class));
}
**/
}

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

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

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

@@ -0,0 +1,59 @@
// This file is part of Friendiqa
// https://git.friendi.ca/lubuwest/Friendiqa
// Copyright (C) 2017 Marco R. <thomasschmidt45@gmx.net>
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// In addition, as a special exception, the copyright holders give
// permission to link the code of portions of this program with the
// OpenSSL library under certain conditions as described in each
// individual source file, and distribute linked combinations including
// the two.
//
// You must obey the GNU General Public License in all respects for all
// of the code used other than OpenSSL. If you modify file(s) with this
// exception, you may extend this exception to your version of the
// file(s), but you are not obligated to do so. If you do not wish to do
// so, delete this exception statement from your version. If you delete
// this exception statement from all source files in the program, then
// also delete it here.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.

#ifndef ALARM_H
#define ALARM_H

#include <QObject>

class ALARM : public QObject
{
Q_OBJECT
//Q_PROPERTY(int alarmtime READ alarmtime WRITE setAlarm NOTIFY alarmChanged)
public:
static ALARM *instance();

explicit ALARM(QObject *parent = 0);
//int alarmtime() const;

signals:

void alarmChanged(QString url);

public slots:
void setAlarm(int time);

private:
int m_time;
};

#endif // UPDATENEWS_H

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

@@ -0,0 +1,82 @@
// This file is part of Friendiqa
// https://git.friendi.ca/lubuwest/Friendiqa
// Copyright (C) 2017 Marco R. <thomasschmidt45@gmx.net>
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// In addition, as a special exception, the copyright holders give
// permission to link the code of portions of this program with the
// OpenSSL library under certain conditions as described in each
// individual source file, and distribute linked combinations including
// the two.
//
// You must obey the GNU General Public License in all respects for all
// of the code used other than OpenSSL. If you modify file(s) with this
// exception, you may extend this exception to your version of the
// file(s), but you are not obligated to do so. If you do not wish to do
// so, delete this exception statement from your version. If you delete
// this exception statement from all source files in the program, then
// also delete it here.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.

//#include <QtAndroidExtras/QAndroidJniObject>
//#include <QtAndroidExtras/QAndroidJniEnvironment>
#include "alarm.h"
#include <QtCore/QDebug>
#include "AndroidNative/systemdispatcher.h"

ALARM *ALARM::instance()
{
static ALARM alarm;
return &alarm;
}

ALARM::ALARM(QObject *parent) : QObject(parent){}

void ALARM::setAlarm(int interval)
{
qDebug() << interval;
QVariantMap message;
message["value"] = interval;
AndroidNative::SystemDispatcher::instance()->loadClass("androidnative.Util");
AndroidNative::SystemDispatcher::instance()->dispatch("androidnative.Util.setSchedule", message);
//AndroidNative::SystemDispatcher::instance()->dispatch("androidnative.Util.stopService", message);
// auto activity = QtAndroid::androidActivity();
// auto packageManager = activity.callObjectMethod("getPackageManager",
// "()Landroid/content/pm/PackageManager;");

// auto activityIntent = packageManager.callObjectMethod("getLaunchIntentForPackage",
// "(Ljava/lang/String;)Landroid/content/Intent;",
// activity.callObjectMethod("getPackageName",
// "()Ljava/lang/String;").object());

// auto pendingIntent = QAndroidJniObject::callStaticObjectMethod("android/app/PendingIntent", "getActivity",
// "(Landroid/content/Context;ILandroid/content/Intent;I)Landroid/app/PendingIntent;",
// activity.object(), jint(0), activityIntent.object(),
// QAndroidJniObject::getStaticField<jint>("android/content/Intent",
// "FLAG_ACTIVITY_CLEAR_TOP"));

// auto alarmManager = activity.callObjectMethod("getSystemService",
// "(Ljava/lang/String;)Ljava/lang/Object;",
// QAndroidJniObject::getStaticObjectField("android/content/Context",
// "ALARM_SERVICE",
// "Ljava/lang/String;").object());

// alarmManager.callMethod<void>("set",
// "(IJLandroid/app/PendingIntent;)V",
// QAndroidJniObject::getStaticField<jint>("android/app/AlarmManager", "RTC"),
// jlong(QDateTime::currentMSecsSinceEpoch() + 100), pendingIntent.object());


}


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

@@ -31,10 +31,14 @@

#include <QApplication>
#include <QtQml/QQmlEngine>
#include <QAndroidService>
#include <QtAndroid>
#include <QtQuick>
#include "xhr.h"
#include "updatenews.h"
#include "filesystem.h"
#include "remoteauthasyncimageprovider.h"
#include "alarm.h"
#include "AndroidNative/systemdispatcher.h"
#include "AndroidNative/environment.h"
//#include "AndroidNative/debug.h"
@@ -55,6 +59,20 @@ JNIEXPORT jint JNI_OnLoad(JavaVM* vm, void*) {


int main(int argc, char *argv[]) {
//qDebug()<< "argv Friendiqa"<< argv[0] <<" argv2" <<argv[1];
if (qstrcmp(argv[1],"-service")==0){
//qDebug()<<"FriendiqaMain Service";
QAndroidService app(argc, argv);
UPDATENEWS* updatenews= UPDATENEWS::instance();
updatenews->setDatabase();
updatenews->login();
updatenews->timeline();
app.connect (updatenews,SIGNAL(quitapp()),&app,SLOT(quit()));
//QtAndroid::androidService().callMethod<void>("stopSelf");
return app.exec();
}
else{
QApplication app(argc, argv);
QQuickView view;
QTranslator qtTranslator;
@@ -67,10 +85,14 @@ int main(int argc, char *argv[]) {
view.rootContext()->setContextProperty("xhr", xhr);
FILESYSTEM* filesystem = FILESYSTEM::instance();
view.rootContext()->setContextProperty("filesystem", filesystem);
ALARM* alarm = ALARM::instance();
view.rootContext()->setContextProperty("alarm", alarm);
// UPDATENEWS* updatenews = UPDATENEWS::instance();
// view.rootContext()->setContextProperty("updatenews", updatenews);
view.setSource(QUrl("qrc:/qml/friendiqa.qml"));
view.show();
view.connect(view.rootContext()->engine(), SIGNAL(quit()), &app, SLOT(quit()));
return app.exec();
}
}


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

@@ -0,0 +1,399 @@
// This file is part of Friendiqa
// https://git.friendi.ca/lubuwest/Friendiqa
// Copyright (C) 2017 Marco R. <thomasschmidt45@gmx.net>
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// In addition, as a special exception, the copyright holders give
// permission to link the code of portions of this program with the
// OpenSSL library under certain conditions as described in each
// individual source file, and distribute linked combinations including
// the two.
//
// You must obey the GNU General Public License in all respects for all
// of the code used other than OpenSSL. If you modify file(s) with this
// exception, you may extend this exception to your version of the
// file(s), but you are not obligated to do so. If you do not wish to do
// so, delete this exception statement from your version. If you delete
// this exception statement from all source files in the program, then
// also delete it here.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.

#include "updatenews.h"

#include <QHttpPart>
#include <QTextCodec>
#include <QUrlQuery>
#include <QList>
#include <QDataStream>
#include <QJsonDocument>
#include <QJsonObject>
#include <QJsonArray>
#include <QQmlEngine>
#include <QSqlQuery>
#include <QSqlRecord>
#include <QSqlDatabase>
#include <QSqlError>
#include <QDateTime>
//#include "AndroidNative/systemdispatcher.h"



UPDATENEWS *UPDATENEWS::instance()
{
static UPDATENEWS udn;
return &udn;
}

UPDATENEWS::UPDATENEWS(QObject *parent) : QObject(parent)
{

}

void UPDATENEWS::setUrl(QString url)
{
if (url!=m_url) {
m_url = url;
xhr.setUrl(url);
emit urlChanged(m_url);
}
}


void UPDATENEWS::setDatabase()
{
static QQmlEngine qe;
QString db_url=qe.offlineStorageDatabaseFilePath("Friendiqa");
m_db = QSqlDatabase::addDatabase("QSQLITE");
m_db.setDatabaseName(QUrl("file://"+db_url+".sqlite").toLocalFile());
//qDebug() << db_url;

if (!m_db.open())
{
qDebug() << "Error: connection with database fail " << m_db.lastError();
}
}


void UPDATENEWS::login()
{
QSqlQuery query("SELECT * FROM config WHERE isActive=0",m_db);
while (query.next())
{
username = query.value(1).toString();
QByteArray bpassword=query.value(2).toByteArray();
QString password=QByteArray::fromBase64(bpassword);
m_login=username+":"+password ;
xhr.setLogin(m_login);
m_url=query.value(0).toString();
xhr.setUrl(m_url);
m_imagedir=query.value(3).toString();
xhr.setImagedir(m_imagedir);
QString isActive=query.value(7).toString();
m_updateInterval=query.value(5).toInt();
m_api="/api/statuses/friends_timeline";
xhr.setApi(m_api);
}
}


void UPDATENEWS::timeline()
{
qDebug()<<"Friendiqa start timeline";
QSqlQuery query("SELECT status_id FROM news WHERE username='"+ username +"' ORDER BY status_id DESC LIMIT 1",m_db);
if (query.isActive() && query.isSelect()){query.first();};
QString lastid=query.value(0).toString();
xhr.clearParams();
xhr.setParam("since_id",lastid);
xhr.setParam("count","50");
xhr.get();
QObject::connect(&xhr,SIGNAL(success(QByteArray,QString)),this,SLOT(store(QByteArray,QString)));
QObject::connect(&xhr,SIGNAL(error(QString,QString,QString,int)),this,SLOT(showError(QString,QString,QString,int)));
}


//void UPDATENEWS::startservice(QString type,QVariantMap map)
//{
// qDebug ()<<"Friediqa start service "<<type;
// if (type=="androidnativeServiceStarted"){
// setDatabase();
// login();
// timeline();
// }
//}

void UPDATENEWS::store(QByteArray serverreply,QString apiname)
{
QJsonDocument news;
qDebug()<<apiname << news;
QJsonParseError jsonerror;
news=QJsonDocument::fromJson(serverreply,&jsonerror);
if (news.isArray()){
for (int i=0; i < news.array().count();i++){
QJsonValue newsitem=news[i];
QSqlQuery query(m_db);
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 (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)");
query.bindValue(0,username);
query.bindValue(1,"0");
query.bindValue(2, newsitem["text"].toString().toUtf8().toBase64());
QString sourcedate=newsitem["created_at"].toString();
QString formateddate=sourcedate.mid(0,3)+", "+sourcedate.mid(8,3)+sourcedate.mid(4,3)+sourcedate.mid(25,5)+sourcedate.mid(10,15);
query.bindValue(3,QDateTime::fromString(formateddate,Qt::RFC2822Date).toMSecsSinceEpoch() );
if(newsitem["in_reply_to_status_id"]!=QJsonValue::Null){query.bindValue(4, newsitem["in_reply_to_status_id"].toInt());};
query.bindValue(5,newsitem["source"]);
query.bindValue(6,newsitem["id"].toInt());
if(newsitem["in_reply_to_user_id"]!=QJsonValue::Null){ query.bindValue(7,newsitem["in_reply_to_user_id"].toInt());};
query.bindValue(8,newsitem["geo"]);
query.bindValue( 9, newsitem["favorited"].toInt());
query.bindValue(10, newsitem["user"]["id"].toInt());
query.bindValue(11, newsitem["statusnet_html"].toString().toUtf8().toBase64());
query.bindValue(12, newsitem["statusnet_conversation_id"].toInt());
QJsonArray likeArray;QJsonArray dislikeArray;QJsonArray attendyesArray;QJsonArray attendnoArray;QJsonArray attendmaybeArray;
if (newsitem.toObject().contains("friendica_activities")){
for (int a=0; a < newsitem["friendica_activities"]["like"].toArray().count();a++){
likeArray.append(newsitem["friendica_activities"]["like"][a]["url"].toString());
}
for (int b=0; b < newsitem["friendica_activities"]["dislike"].toArray().count();b++){
dislikeArray.append(newsitem["friendica_activities"]["dislike"][b]["url"].toString());
}
for (int c=0; c < newsitem["friendica_activities"]["attendyes"].toArray().count();c++){
attendyesArray.append(newsitem["friendica_activities"]["attendyes"][c]["url"].toString());
}
for (int d=0; d < newsitem["friendica_activities"]["attendno"].toArray().count();d++){
attendnoArray.append(newsitem["friendica_activities"]["attendno"][d]["url"].toString());
}
for (int e = 0; e < newsitem["friendica_activities"]["attendmaybe"].toArray().count();e++){
attendmaybeArray.append(newsitem["friendica_activities"]["attendmaybe"][e]["url"].toString());
}
};
QJsonArray friendica_activities; friendica_activities={likeArray,dislikeArray,attendyesArray,attendnoArray,attendmaybeArray};
QJsonDocument activities; activities.setArray(friendica_activities);
query.bindValue(13,activities.toJson(QJsonDocument::Compact).toBase64());
query.bindValue(14,"[]");

if (newsitem["attachments"]!=QJsonValue::Undefined){
query.bindValue(15, QJsonDocument(newsitem["attachments"].toArray()).toJson(QJsonDocument::Compact).toBase64());
};

query.bindValue(16, newsitem["friendica_owner"]["url"]);
query.exec() ;
}
}
else {
qDebug()<< "Friendiqa updatenews error";
emit this->error(m_api,QTextCodec::codecForName("utf-8")->toUnicode(serverreply));
if(m_updateInterval!=0){
m_db.close();
m_db.removeDatabase(m_db.connectionName());
emit quitapp();
alarm.setAlarm(m_updateInterval);
};
}
QList<QJsonValue> newcontacts=findNewContacts(news);
updateContacts(newcontacts);
startImagedownload();
connect(&xhr, SIGNAL(downloaded(QString, QString, QString, int)), this, SLOT(updateImageLocation(QString,QString, QString, int)));

}

void UPDATENEWS::updateImageLocation(QString downloadtype,QString imageurl, QString filename, int index){
if (downloadtype=="contactlist"){
QSqlQuery testquery("SELECT profile_image FROM contacts WHERE profile_image_url ='"+imageurl+ "' AND username = '" +username+"'",m_db);
testquery.exec();
//qDebug()<< "update imageurl for " <<imageurl << " from " <<testquery.value(0).toString() <<" to "<< filename <<" index " << index << " newcontactnames.length " <<newcontactnames.length();
QSqlQuery query("UPDATE contacts SET profile_image='"+ filename +"' WHERE profile_image_url ='"+imageurl+ "' AND username = '" +username+"'",m_db);
query.exec();
if (index==(newcontactnames.length()-1)){
if(m_updateInterval!=0){
m_db.close();
m_db.removeDatabase(m_db.connectionName());
emit quitapp();
alarm.setAlarm(m_updateInterval);
};
}
}
}

QList <QJsonValue> UPDATENEWS::findNewContacts(QJsonDocument news){
QSqlQuery query("SELECT profile_image_url FROM contacts",m_db);
QList<QString> imageurls;
while (query.next()){
imageurls.append(query.value(0).toString());
}
QList<QJsonValue> newcontacts;
qDebug()<<"updatenews findcontacts count "<<news.array().count();

for (int i=0; i<news.array().count();i++){
//main contacts
if(imageurls.contains(news[i]["user"]["profile_image_url"].toString()) || newcontactimagelinks.contains(news[i]["user"]["profile_image_url"].toString())){
}
else{
newcontacts.append(news[i]["user"]);
newcontactimagelinks.append(news[i]["user"]["profile_image_url"].toString());
newcontactnames.append(news[i]["user"]["screen_name"].toString());
}
//like/dislike contacts
if (news[i].toObject().contains("friendica_activities") ){
for (int a=0; a < news[i]["friendica_activities"]["like"].toArray().count();a++){
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())){
}
else{
newcontacts.append(news[i]["friendica_activities"]["like"][a]);
newcontactimagelinks.append(news[i]["friendica_activities"]["like"][a]["profile_image_url"].toString());
newcontactnames.append(news[i]["friendica_activities"][a]["screen_name"].toString());
}
}
for (int b=0; b < news[i]["friendica_activities"]["dislike"].toArray().count();b++){
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())){
}
else{
newcontacts.append(news[i]["friendica_activities"]["dislike"][b]);
newcontactimagelinks.append(news[i]["friendica_activities"]["dislike"][b]["profile_image_url"].toString());
newcontactnames.append(news[i]["friendica_activities"][b]["screen_name"].toString());
}
}
}
//owner contacts
if (news[i].toObject().contains("friendica_owner") ){
if(imageurls.contains(news[i]["friendica_owner"]["profile_image_url"].toString()) || newcontactimagelinks.contains(news[i]["friendica_owner"]["profile_image_url"].toString())){
}
else{
newcontacts.append(news[i]["friendica_owner"]);
newcontactimagelinks.append(news[i]["friendica_owner"]["profile_image_url"].toString());
newcontactnames.append(news[i]["friendica_owner"]["screen_name"].toString());
}
}
}
return newcontacts;
}


void UPDATENEWS::updateContacts(QList<QJsonValue> contacts){
qint64 currentTime =QDateTime::currentMSecsSinceEpoch();
for (int i=0; i < contacts.count();i++){
QJsonValue contact=contacts[i];
QSqlQuery query(m_db);
//qDebug() << "updatecontact " << contact["screen_name"];
QSqlQuery testquery("SELECT url FROM contacts WHERE username='"+ username +"' AND url='" + contact["url"].toString() +"'",m_db);
if (testquery.first()){
query.prepare("UPDATE contacts SET id=?, name=?, screen_name=?, location=?,imageAge=?,"
"profile_image_url=?, description=?, protected=?, followers_count=?,"
"friends_count=?, created_at=?, favourites_count=?, utc_offset=?, time_zone=?, statuses_count=?,"
"following=?, verified=?, statusnet_blocking=?, notifications=?, statusnet_profile_url=?, cid=?, network=?, timestamp=? "
" WHERE username='"+ username +"' AND url='" + contact["url"].toString() +"'");
query.bindValue(0, contact["id"].toInt());
query.bindValue(1, contact["name"].toString().toUtf8().toBase64());
query.bindValue(2, contact["screen_name"]);
query.bindValue(3, contact["location"]);
query.bindValue(4, currentTime);
query.bindValue(5, contact["profile_image_url"]);
if(contact["description"].isNull() ){query.bindValue(6,"");}else{query.bindValue(6, contact["description"].toString().toUtf8().toBase64());};
query.bindValue(7,contact["protected"].toBool());
query.bindValue(8,contact["followers_count"].toInt());
query.bindValue(9,contact["friends_count"].toInt());
QString sourcedate=contact["created_at"].toString();
QString formateddate=sourcedate.mid(0,3)+", "+sourcedate.mid(8,3)+sourcedate.mid(4,3)+sourcedate.mid(25,5)+sourcedate.mid(10,15);
query.bindValue(10,QDateTime::fromString(formateddate,Qt::RFC2822Date).toMSecsSinceEpoch() );
query.bindValue(11,contact["favorites_count"].toInt());
query.bindValue(12,contact["utc_offset"].toInt());
query.bindValue(13,contact["time_zone"].toString());
query.bindValue(14,contact["statuses_count"].toInt());
query.bindValue(15,contact["following"].toBool());
query.bindValue(16,contact["verfied"].toBool());
query.bindValue(17,contact["statusnet_blocking"].toBool());
query.bindValue(18,contact["notifications"].toBool());
query.bindValue(19,contact["statusnet_profile_url"]);
query.bindValue(20,contact["cid"].toInt());
query.bindValue(21,contact["network"]);
qint64 timestamp=0;
QString timestamphelper=contact["profile_image_url"].toString();
try {timestamp=timestamphelper.mid(timestamphelper.indexOf("?ts")+4,timestamphelper.length()).toUInt();} catch(...){};
query.bindValue(22,timestamp);
}

else{
query.prepare("INSERT INTO contacts (username, id, name, screen_name, location,imageAge,"
"profile_image_url, description, profile_image, url, protected, followers_count,"
"friends_count, created_at, favourites_count, utc_offset, time_zone, statuses_count,"
"following, verified, statusnet_blocking, notifications, statusnet_profile_url, cid, network, isFriend, timestamp)"
"VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)");

query.bindValue(0,username);
query.bindValue(1, contact["id"].toInt());
query.bindValue(2, contact["name"].toString().toUtf8().toBase64());
query.bindValue(3, contact["screen_name"]);
query.bindValue(4, contact["location"]);
query.bindValue(5, currentTime);
query.bindValue(6, contact["profile_image_url"]);
if(contact["description"].isNull() ){query.bindValue(7,"");}else{query.bindValue(7, contact["description"].toString().toUtf8().toBase64());};
query.bindValue(8,"none");
query.bindValue(9, contact["url"].toString());
query.bindValue(10,contact["protected"].toBool());
query.bindValue(11,contact["followers_count"].toInt());
query.bindValue(12,contact["friends_count"].toInt());
QString sourcedate=contact["created_at"].toString();
QString formateddate=sourcedate.mid(0,3)+", "+sourcedate.mid(8,3)+sourcedate.mid(4,3)+sourcedate.mid(25,5)+sourcedate.mid(10,15);
query.bindValue(13,QDateTime::fromString(formateddate,Qt::RFC2822Date).toMSecsSinceEpoch() );
query.bindValue(14,contact["favorites_count"].toInt());
query.bindValue(15,contact["utc_offset"].toInt());
query.bindValue(16,contact["time_zone"].toString());
query.bindValue(17,contact["statuses_count"].toInt());
query.bindValue(18,contact["following"].toBool());
query.bindValue(19,contact["verfied"].toBool());
query.bindValue(20,contact["statusnet_blocking"].toBool());
query.bindValue(21,contact["notifications"].toBool());
query.bindValue(22,contact["statusnet_profile_url"]);
query.bindValue(23,contact["cid"].toInt());
query.bindValue(24,contact["network"]);
query.bindValue(25, 0);
qint64 timestamp=0;
QString timestamphelper=contact["profile_image_url"].toString();
try {timestamp=timestamphelper.mid(timestamphelper.indexOf("?ts")+4,timestamphelper.length()).toUInt();} catch(...){};
query.bindValue(26,timestamp);

}
query.exec() ;
}
emit this->success(m_api);
if ((contacts.count()==0) && (m_updateInterval!=0)){
m_db.close();
m_db.removeDatabase(m_db.connectionName());
emit quitapp();
alarm.setAlarm(m_updateInterval);
};
}

QString UPDATENEWS::url() const
{
return m_url;
}

void UPDATENEWS::startImagedownload()
{
xhr.setDownloadtype("contactlist");
xhr.setFilelist(newcontactimagelinks);
xhr.setContactlist(newcontactnames);
xhr.setImagedir(m_imagedir);
xhr.getlist();
}

void UPDATENEWS::showError(QString data, QString url,QString api, int code )
{
emit this->error(api,data);
if(m_updateInterval!=0){
m_db.close();
m_db.removeDatabase(m_db.connectionName());
emit quitapp();
alarm.setAlarm(m_updateInterval);
};
}

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

@@ -0,0 +1,92 @@
// This file is part of Friendiqa
// https://git.friendi.ca/lubuwest/Friendiqa
// Copyright (C) 2017 Marco R. <thomasschmidt45@gmx.net>
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// In addition, as a special exception, the copyright holders give
// permission to link the code of portions of this program with the
// OpenSSL library under certain conditions as described in each
// individual source file, and distribute linked combinations including
// the two.
//
// You must obey the GNU General Public License in all respects for all
// of the code used other than OpenSSL. If you modify file(s) with this
// exception, you may extend this exception to your version of the
// file(s), but you are not obligated to do so. If you do not wish to do
// so, delete this exception statement from your version. If you delete
// this exception statement from all source files in the program, then
// also delete it here.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.

#ifndef UPDATENEWS_H
#define UPDATENEWS_H

#include <QObject>
#include <QJsonObject>
#include <QSqlDatabase>
#include "xhr.h"
#include "alarm.h"
#include "AndroidNative/systemdispatcher.h"

class UPDATENEWS : public QObject
{
Q_OBJECT
Q_PROPERTY(QString url READ url WRITE setUrl NOTIFY urlChanged)
// Q_PROPERTY(QString login READ login NOTIFY loginChanged)
public:
static UPDATENEWS *instance();

explicit UPDATENEWS(QObject *parent = 0);
QString url() const;
//QString login() const;

signals:

void urlChanged(QString url);
void success(QString api);
void error(QString api, QString content);
void quitapp();

public slots:
void setUrl(QString url);
void setDatabase();
void login();
void timeline();
//void startservice(QString type,QVariantMap map);
void startImagedownload();
void updateImageLocation(QString downloadtype,QString imageurl, QString filename, int index);
void store(QByteArray serverreply,QString apiname);
void showError(QString data, QString url,QString api, int code);

private:
QString m_url;
QString m_api;
QString m_imagedir;
QString m_login;
QString username;
QSqlDatabase m_db;
QList<QJsonValue> findNewContacts(QJsonDocument news);
int m_updateInterval;
//void timeline();
//void store(QByteArray serverreply,QString apiname);
void updateContacts(QList<QJsonValue> contacts);

XHR xhr;
ALARM alarm;
QList<QString> newcontactimagelinks;
QList<QString> newcontactnames;
};

#endif // UPDATENEWS_H

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

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


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

@@ -79,7 +79,7 @@ signals:
void networktypeChanged();
void downloaded(QString type, QString url, QString filename, int i);
void downloadedjson(QString type, QString url, QString filename, int i,QJsonObject jsonObject);
void success(QString data, QString api);
void success(QByteArray data, QString api);
void error(QString data, QString url,QString api, int code);

public slots:


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

@@ -21,7 +21,9 @@ SOURCES += common/friendiqa.cpp \
common/uploadableimage.cpp \
common/xhr.cpp \
common/filesystem.cpp \
common/remoteauthasyncimageprovider.cpp
common/remoteauthasyncimageprovider.cpp \
common/updatenews.cpp \
common/alarmandroid.cpp

ANDROID_PACKAGE_SOURCE_DIR = $$PWD/android

@@ -38,14 +40,17 @@ OTHER_FILES += qml/friendiqa.qml \
js/*.js

TRANSLATIONS += translations/friendiqa-de.ts \
translations/friendiqa-es.ts
translations/friendiqa-es.ts \
translations/friendiqa-it.ts

HEADERS += \
common/uploadableimage.h \
common/xhr.h \
common/filesystem.h \
common/remoteauthasyncimageprovider.h
common/remoteauthasyncimageprovider.h \
common/updatenews.h \
common/alarm.h

DISTFILES += \
qml/calendarqml/*.qml \
android/AndroidManifest.xml \


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

@@ -95,6 +95,20 @@ function friendicaWebRequest(url,rootwindow,callback) {
xhrequest.send();
}

function friendicaXmlRequest(url,rootwindow,callback) {
var xhrequest = new XMLHttpRequest();
xhrequest.onreadystatechange = function() {
if (xhrequest.readyState === XMLHttpRequest.HEADERS_RECEIVED) {}
else if(xhrequest.readyState === XMLHttpRequest.DONE) {
try{callback(xhrequest.responseXML)}
catch (e){showMessage("Error","API:\n" +url+" "+e+"\n Return: "+xhrequest.responseText, rootwindow)}
}
}
xhrequest.open("GET", url);
xhrequest.responseType ="document";
xhrequest.send();
}

function friendicaRemoteAuthRequest(login,url,c_url,rootwindow,callback) {
var xhrequest = new XMLHttpRequest();
xhrequest.onreadystatechange = function() {


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

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


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

@@ -135,6 +135,21 @@ else{
if ((attachmentList.length==0) || (attachmentList[attachmentList.length-1].url!=ptvideohelper.url)){attachmentList.push(ptvideohelper)}
}
}
// if (newsitemobject.text.indexOf("https://www.youtube.com/watch")>-1){
// //print("message "+msg.options.showWebsiteForLinks);
// if (msg.options.showYoutube!="false"){
// var ythelper={mimetype:"video/youtube"}
// var yttext=newsitemobject.text;
// while (yttext.indexOf("https://www.youtube.com/watch")>-1){
// var ythelperstringposition=linktext.indexOf("watch?v=");
// var ytposend=findend(yttext,ythelperstringposition);
// ythelper.url=yttext.substring(yttext.lastIndexOf("http",linkhelperstringposition),linkposend);
// linktext=linktext.substring(linkhelperstringposition+5,linktext.length)
// if ((attachmentList.length==0) || (attachmentList[attachmentList.length-1].url!=linkhelper.url)){attachmentList.push(linkhelper)}
// }
// }
// }
// if (newsitemobject.text.indexOf(".html")>-1){
// //print("message "+msg.options.showWebsiteForLinks);
// if (msg.options.showWebsiteForLinks!="false"){


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

@@ -513,9 +513,6 @@ function updateView(viewtype){
//downloadNotice.text="xhr start "+Date.now()
switch(viewtype){
case "Conversations":
// updatenews.setDatabase();
// updatenews.login();
// updatenews.timeline();
var lastnews=Newsjs.getLastNews(login,db);
xhr.setLogin(login.username+":"+Qt.atob(login.password));
xhr.setUrl(login.server);
@@ -525,9 +522,6 @@ function updateView(viewtype){
xhr.setParam("count",50)
break;
case "Timeline":
// updatenews.setDatabase();
// updatenews.login();
// updatenews.timeline();
var lastnews=Newsjs.getLastNews(login,db);
xhr.setLogin(login.username+":"+Qt.atob(login.password));
xhr.setUrl(login.server);
@@ -565,6 +559,12 @@ function updateView(viewtype){
xhr.setApi("/api/favorites");
xhr.clearParams();
break;
case "Replies":
xhr.setLogin(login.username+":"+Qt.atob(login.password));
xhr.setUrl(login.server);
xhr.setApi("/api/statuses/replies");
xhr.clearParams();
break;
default:
var lastnews=Newsjs.getLastNews(login,db);
xhr.setLogin(login.username+":"+Qt.atob(login.password));
@@ -575,8 +575,8 @@ function updateView(viewtype){
xhr.setParam("count",50)
newstab.newstabstatus="Conversations";
}
xhr.get();

xhr.get();
if (viewtype==="Conversations"){Newsjs.allchatsfromdb(db,login.username,function(temp){
newsStack.allchats=temp
})}


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

@@ -0,0 +1,45 @@
<html>
<head>
<title>-1</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no"/>
</head>
<body bgcolor="black" marginwidth="0" marginheight="0">
<div id="player"></div>
<script>
function getVideoId() {
return window.location.href.slice(window.location.href.indexOf('?') + 1);
}
var tag = document.createElement('script');
tag.src = "https://www.youtube.com/iframe_api";
var firstScriptTag = document.getElementsByTagName('script')[0];
firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);
var player;
function onYouTubeIframeAPIReady() {
player = new YT.Player('player', {
playerVars: { 'html5': 1, 'iv_load_policy': 3 },
frameborder: '0',
height: '100%',
width: '100%',
videoId: getVideoId(),
events: {
'onReady': onPlayerReady,
'onStateChange': onPlayerStateChange
}
});
}
function onPlayerReady(event) {
document.title = 0;
}

function onPlayerStateChange(event) {
if (event.data == YT.PlayerState.PLAYING) {
document.title = 1;
} else if (event.data == YT.PlayerState.ENDED || event.data == YT.PlayerState.PAUSED) {
document.title = 2;
}
}
</script>
</body>
</html>

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

@@ -93,99 +93,106 @@ StackView{
}

Text {
text: qsTr("Server")
x: 4*mm; y: 10*mm
text: qsTr("Server")
font.pixelSize:3*mm
x: 4*mm; y: 10*mm
}
Text {
text: qsTr("Nickname")
x: 4*mm; y: 20*mm
text: qsTr("Nickname")
font.pixelSize:3*mm
x: 4*mm; y: 20*mm
}

Text {
text: qsTr("Password")
x: 4*mm; y: 30*mm
font.pixelSize:3*mm
x: 4*mm; y: 30*mm
}
Text {
text: qsTr("Image dir.")
x: 4*mm; y: 40*mm
text: qsTr("Image dir.")
font.pixelSize:3*mm
x: 4*mm; y: 40*mm
}

Text {
text: qsTr("Max. News")
x: 4*mm; y: 50*mm
}
Text {
text: qsTr("News as")
x: 4*mm; y: 60*mm
Text {
text: qsTr("Max. News")
font.pixelSize:3*mm
x: 4*mm; y: 50*mm
}
Text {
text: qsTr("Interval (0=None)")
visible: false
x: 4*mm; y: 70*mm; width:20*mm;wrapMode: Text.Wrap
}
text: qsTr("News as")
font.pixelSize:3*mm
x: 4*mm; y: 60*mm
}
Text {
text: qsTr("Sync Interval (0=None)")
font.pixelSize:3*mm
//visible: false
x: 4*mm; y: 70*mm; //width:35*mm;wrapMode: Text.Wrap
}
// Text {
// Text {
// text: qsTr("Show Website")
// x: 4*mm; y: 70*mm; width: 20*mm
// }

Image{
id:servericon
x:19*mm;y:10*mm
width:5*mm; height: 5*mm
visible: false
source:""
MouseArea{
anchors.fill:parent
onClicked:{
Service.showServerConfig(servername.text, configBackground, function(configString){
var serverconfigObject=Qt.createQmlObject(configString,configBackground,"serverconfigOutput");})
}
}
}
// x: 4*mm; y:80*mm; width: 20*mm
// }

BlueButton{
id:serverSearchButton
text:"\uf002"
x:19*mm
y:10*mm
width: 5*mm; height:5*mm
visible: servericon.visible?false:true
onClicked:{Qt.openUrlExternally(Qt.resolvedUrl("https://dir.friendica.social/servers"))}
Image{
id:servericon
x:4*mm;y:13.5*mm
width:5*mm; height: 5*mm
visible: false
source:""
MouseArea{
anchors.fill:parent
onClicked:{
Service.showServerConfig(servername.text, configBackground, function(configString){
var serverconfigObject=Qt.createQmlObject(configString,configBackground,"serverconfigOutput");})
}
}
}

BlueButton{
id:serverSearchButton
text:"\uf002"
x:4*mm
y:13.5*mm
width: 5*mm; height:5*mm
visible: servericon.visible?false:true
onClicked:{Qt.openUrlExternally(Qt.resolvedUrl("https://dir.friendica.social/servers"))}
}

Rectangle{color: "light grey"; x: 25*mm; y: 10*mm; width: root.width/2; height: 5*mm;}
Flickable {
id: servernameFlickable
x: 25*mm; y: 10*mm; width: root.width/2; height: 5*mm;
contentWidth: servername.paintedWidth
contentHeight: servername.paintedHeight
clip: true
TextEdit {
id: servername
width: servernameFlickable.width
height: servernameFlickable.height
focus: true
text:"https://..."
onEditingFinished:{
Rectangle{color: "light grey"; x: 10*mm; y: 13.5*mm; width: root.width-12*mm; height: 5*mm;}
Flickable {
id: servernameFlickable
x: 10*mm; y: 13.5*mm; width: root.width-12*mm; height: 5*mm;
contentWidth: servername.paintedWidth
contentHeight: servername.paintedHeight
clip: true
TextEdit {
id: servername
width: servernameFlickable.width
height: servernameFlickable.height
focus: true
font.pixelSize:3*mm
text:"https://..."
onEditingFinished:{
if((servername.text).substring(0,14) =="https://...http"){
serverstring.text= (serverstring.text).substring(11)
}

configBackground.setServericon(servername.text)
}
onCursorRectangleChanged: Layoutjs.ensureVisibility(cursorRectangle,servernameFlickable)
}
}
}
}

Rectangle{
color: "light grey"
x: 25*mm; y: 20*mm; width: root.width/2-9*mm; height: 5*mm;
TextInput {
id: username
anchors.fill: parent
selectByMouse: true
Rectangle{
color: "light grey"
x: 4*mm; y: 23.5*mm; width: root.width-14*mm; height: 5*mm;
TextInput {
id: username
anchors.fill: parent
font.pixelSize:3*mm
selectByMouse: true
onEditingFinished:{
if (username.text.indexOf('@')>-1){
Helperjs.showMessage(qsTr("Error"),qsTr("Nicknames containing @ symbol currently not supported"),configBackground)
@@ -201,47 +208,71 @@ StackView{
}
}
}
BlueButton {
x: root.width/2+18*mm; y: 20*mm; width:7*mm
text: "\uf234"
onClicked: {
configStack.push({item:"qrc:/qml/configqml/RegisterPage.qml",properties:{url:servername.text+"/register?nickname="+username.getText(0,username.length)}})
}
}
BlueButton {
x: root.width-9*mm; y: 23.5*mm; width:7*mm
text: "\uf234"
onClicked: {
configStack.push({item:"qrc:/qml/configqml/RegisterPage.qml",properties:{url:servername.text+"/register?nickname="+username.getText(0,username.length)}})
}
}

Rectangle{
color: "light grey"
x: 25*mm; y: 30*mm; width: root.width/2; height: 5*mm;
x: 4*mm; y: 33.5*mm; width: root.width-6*mm; height: 5*mm;
TextInput {
id: password
anchors.fill: parent
font.pixelSize:3*mm
selectByMouse: true
echoMode: TextInput.PasswordEchoOnEdit
}
}

Rectangle{color: "light grey"; x: 25*mm; y: 40*mm; width: root.width/2-9*mm; height: 5*mm;}
Rectangle{color: "light grey"; x: 4*mm; y: 43.5*mm; width: root.width-14*mm; height: 5*mm;}
Flickable {
id: imagestoreFlickable
x: 25*mm; y: 40*mm; width: root.width/2-9*mm; height: 5*mm;
x: 4*mm; y: 43.5*mm; width: root.width-14*mm; height: 5*mm;
clip: true
TextInput {
id: imagestore
width: imagestoreFlickable.width
height: imagestoreFlickable.height
font.pixelSize:3*mm
wrapMode: TextEdit.NoWrap
onCursorRectangleChanged: Layoutjs.ensureVisibility(cursorRectangle,imagestoreFlickable)
}
}

FileDialog {
id: imagestoreDialog
title: "Please choose a directory"
folder: shortcuts.pictures
selectFolder: true
onAccepted: {
var imagestoreString=imagestoreDialog.folder.toString();
imagestoreString=imagestoreString.replace(/^(file:\/{2})/,"")+"/"
imagestore.text=imagestoreString
}
}

BlueButton {
x: root.width-9*mm; y: 43.5*mm; width: 7*mm; height: 5*mm;
text: "..."
onClicked:
{imagestoreDialog.open()}
}


Slider{ id: maxNews
x:34*mm; y: 50*mm;width: root.width/3;height:5*mm
x:19*mm; y: 53.5*mm;width: root.width/2;height:5*mm
minimumValue: 0;maximumValue:2000; stepSize: 100
}


Rectangle{color: "light grey"; x: 25*mm; y: 50*mm; width: 9*mm; height: 5*mm;
Rectangle{color: "light grey"; x: 4*mm; y: 53.5*mm; width: 9*mm; height: 5*mm;
TextEdit{id:maxNewsText;
anchors.fill: parent
font.pixelSize:3*mm
verticalAlignment:TextEdit.AlignRight
text:maxNews.value
focus: true
@@ -250,60 +281,43 @@ StackView{
}

Rectangle{
x: 25*mm; y: 60*mm; width: root.width/2; height: 5*mm;
x: 4*mm; y: 63.5*mm; width: newsTypeField.contentWidth+2*mm; height: 5*mm;
color:"light grey"
Text{
id: newsTypeField
anchors.fill: parent
text:"Conversations"
id: newsTypeField
anchors.fill: parent
font.pixelSize:3*mm
text:"Conversations"
}
MouseArea{
anchors.fill:parent
onClicked:newstypemenu.popup()
anchors.fill:parent
onClicked:newstypemenu.popup()
}
}
Slider{ id: messageIntervalSlider
visible: false
x:37*mm; y: 70*mm;width: root.width/3;height:5*mm
minimumValue: 0;maximumValue:24; stepSize: 0.5
x:22*mm; y: 73.5*mm;width: root.width/2;height:5*mm
minimumValue: 0;maximumValue:120; stepSize: 15
}
Rectangle{
visible:false
x: 25*mm; y: 70*mm; width: 9*mm; height: 5*mm;
x: 4*mm; y: 73.5*mm; width: 9*mm; height: 5*mm;
TextEdit{
id: messageIntervalField
anchors.fill: parent
verticalAlignment:TextEdit.AlignRight
text:messageIntervalSlider.value
focus: true
selectByMouse: true
id: messageIntervalField
anchors.fill: parent
font.pixelSize:3*mm
verticalAlignment:TextEdit.AlignRight
text:messageIntervalSlider.value
focus: true
selectByMouse: true
}
}

FileDialog {
id: imagestoreDialog
title: "Please choose a directory"
folder: shortcuts.pictures
selectFolder: true
onAccepted: {
var imagestoreString=imagestoreDialog.folder.toString();
imagestoreString=imagestoreString.replace(/^(file:\/{2})/,"")+"/"
imagestore.text=imagestoreString
}
}

BlueButton {
x: root.width/2+18*mm; y: 40*mm; width: 7*mm; height: 5*mm;
text: "..."
onClicked:
{imagestoreDialog.open()}
}


Text{x: 14*mm; y: 73.5*mm; width: 5*mm; height: 5*mm;
font.pixelSize:3*mm
text:qsTr("Min.")
}

// CheckBox{
// id:showwebsiteCheckbox
// x:35*mm;y:70*mm
// x:35*mm;y:80*mm
// onClicked:{
// if (checked==true){
// Service.updateglobaloptions(root.db,"showWebsiteForLinks","true")
@@ -314,11 +328,10 @@ StackView{
// root.globaloptions.showWebsiteForLinks="false"
// }
// }
// }

BlueButton {
x: 25*mm; y: 78*mm
x: 4*mm; y: 83.5*mm
text: qsTr("Confirm")
onClicked:{
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{
root.login=userconfig;
root.news=[];
},"isActive",0);
Service.requestProfile(userconfig,db,root,function(nc){root.newContacts=nc})
Service.requestProfile(userconfig,db,root,function(nc){root.newContacts=nc});
if(osSettings.osType=="Android" && userconfig.timerInterval !=0){
alarm.setAlarm(userconfig.timerInterval);
}
Helperjs.showMessage(qsTr("Success"),qsTr("Name")+": "+credentials.name+"\nScreen Name: "+credentials.screen_name,root)
}
});
@@ -382,7 +398,7 @@ StackView{
imagestore.text="";
maxNews.value=0;
newsTypeField.text="Conversations";
messageIntervalSlider.value=0;
messageIntervalSlider.value=30;
userButton.text=qsTr("User");
Helperjs.readData(db,"config","",function(storedUsers){
storedUsers.sort(function(obj1, obj2) {
@@ -405,7 +421,7 @@ StackView{
imagestore.text=""
maxNews.value=0
newsTypeField.text="Conversations"
messageIntervalSlider.value=0
messageIntervalSlider.value=30
userButton.text=qsTr("User")
}
}
@@ -449,12 +465,12 @@ StackView{
if( obj.isActive==0){userButton.fontColor='black'} else {userButton.fontColor='grey'}},"isActive",0
)
})
//Service.readGlobaloptions(db,function(go){
// Service.readGlobaloptions(db,function(go){
// if (root.globaloptions.showWebsiteForLinks!="false"){showwebsiteCheckbox.checked=true}
//})
// })
}
catch (e){
catch (e){print(e)
Helperjs.friendicaWebRequest("https://dir.friendica.social/servers/surprise",configBackground,function(html){
var bpos=html.indexOf("baseurl");
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{
textFormat: Text.RichText
width: parent.width
wrapMode: Text.WrapAtWordBoundaryOrAnywhere
text: "<b>Friendiqa v0.3.4 </b><br>Licensed under GPL 3 with the exception of OpenSSL <br> "+
text: "<b>Friendiqa v0.4 </b><br>Licensed under GPL 3 with the exception of OpenSSL <br> "+
"Profile <a href='https://freunde.ma-nic.de/profile/friendiqa'>https://freunde.ma-nic.de/profile/friendiqa</a><br>"+
"Sourcecode: <a href='https://git.friendi.ca/LubuWest/Friendiqa'>https://git.friendi.ca/LubuWest/Friendiqa</a><br>"+
"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{
property int appHeight: Screen.desktopAvailableHeight
property int backKey: Qt.Key_Back
//property string attachImageDir:filesystem.cameraPath+"/"
property string osType: "Android"
property string imagePickQml: "ImagePicker"
property string imagePicker:'import QtQuick 2.0; import "qrc:/qml/genericqml";'+
imagePickQml+'{multiple : true;onReady: {attachImageURLs.push(imageUrl);'+


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

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

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

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

}
}
}

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

@@ -38,6 +38,10 @@ Item {

Component.onCompleted: {
SystemDispatcher.setInitialized();
print("timer " + login.timerInterval)
if (login.timerInterval !=0){
alarm.setAlarm(login.timerInterval);
}
}
}


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

@@ -45,8 +45,23 @@ Rectangle{
// WebView {id:htmlview;
// anchors.fill: parent
// }
Component.onCompleted: //Helperjs.friendicaWebRequest(url,parent,function(html){
//print(html);
htmlview.text="Text <iframe src='"+url+"' width = '300px' height = '300px'>"
//})
Component.onCompleted:{

// Helperjs.friendicaWebRequest(url,parent,function(document){
// print(document);

//// var metas = document.getElementsByTagName('meta'); //get all the meta tag elements
//// //iterate through them
//// for (i=0; i<metas.length; i++) {
//// if (metas[i].getAttribute("name") == "keywords") {
//// print(metas[i].getAttribute("content"));
//// }
//// else if (metas[i].getAttribute("name") == "description") {
//// console.log(metas[i].getAttribute("content"));
//// }
//// }
// //print(html);
// htmlview.text=""
// })
}
}

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

@@ -40,6 +40,8 @@ import "qrc:/js/helper.js" as Helperjs
import "qrc:/js/service.js" as Service


import AndroidNative 1.0

Item {
Connections{
target:newstab
@@ -59,6 +61,25 @@ Item {
}
}

// Connections{
// target:xhr
// onError:{
// Helperjs.showMessage(qsTr("Network Error"),"API:\n" +login.server+api+"\n Return: \n"+data,root);
// }
// onSuccess:{
// if (api=="/api/statuses/friends_timeline"){
// // downloadNotice.text=downloadNotice.text+ "\n xhr finished "+Date.now();
// //Service.processNews(api,data);
// if(login.newsViewType=="Timeline"){
// Newsjs.newsfromdb(db,login.username,function(dbnews){showNews(dbnews)})}
// else{Newsjs.chatsfromdb(db,login.username,function(dbnews){
// showNews(dbnews);
// })}
// }
// }
// }