Merge pull request #6431 from osmandapp/TelegramTracksDb
Add ability to save users locations to gpx
This commit is contained in:
commit
5355530feb
10 changed files with 2243 additions and 265 deletions
|
@ -146,4 +146,6 @@ dependencies {
|
||||||
implementation("com.github.HITGIF:TextFieldBoxes:1.4.4") {
|
implementation("com.github.HITGIF:TextFieldBoxes:1.4.4") {
|
||||||
exclude group: 'com.android.support'
|
exclude group: 'com.android.support'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
implementation 'net.sf.kxml:kxml2:2.1.8'
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,9 @@
|
||||||
package net.osmand;
|
package net.osmand;
|
||||||
|
|
||||||
import org.apache.commons.logging.Log;
|
import org.apache.commons.logging.Log;
|
||||||
|
import org.xmlpull.v1.XmlPullParser;
|
||||||
|
import org.xmlpull.v1.XmlPullParserException;
|
||||||
|
import org.xmlpull.v1.XmlSerializer;
|
||||||
|
|
||||||
public class PlatformUtil {
|
public class PlatformUtil {
|
||||||
|
|
||||||
|
@ -143,4 +146,11 @@ public class PlatformUtil {
|
||||||
return getLog(cl.getName());
|
return getLog(cl.getName());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static XmlPullParser newXMLPullParser() throws XmlPullParserException {
|
||||||
|
return new org.kxml2.io.KXmlParser();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static XmlSerializer newSerializer() {
|
||||||
|
return new org.kxml2.io.KXmlSerializer();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,7 +25,7 @@ class TelegramApplication : Application(), OsmandHelperListener {
|
||||||
lateinit var osmandAidlHelper: OsmandAidlHelper private set
|
lateinit var osmandAidlHelper: OsmandAidlHelper private set
|
||||||
lateinit var locationProvider: TelegramLocationProvider private set
|
lateinit var locationProvider: TelegramLocationProvider private set
|
||||||
lateinit var messagesDbHelper: MessagesDbHelper private set
|
lateinit var messagesDbHelper: MessagesDbHelper private set
|
||||||
lateinit var tracksDbHelper: TracksDbHelper private set
|
lateinit var savingTracksDbHelper: SavingTracksDbHelper private set
|
||||||
|
|
||||||
var telegramService: TelegramService? = null
|
var telegramService: TelegramService? = null
|
||||||
|
|
||||||
|
@ -69,7 +69,7 @@ class TelegramApplication : Application(), OsmandHelperListener {
|
||||||
notificationHelper = NotificationHelper(this)
|
notificationHelper = NotificationHelper(this)
|
||||||
locationProvider = TelegramLocationProvider(this)
|
locationProvider = TelegramLocationProvider(this)
|
||||||
messagesDbHelper = MessagesDbHelper(this)
|
messagesDbHelper = MessagesDbHelper(this)
|
||||||
tracksDbHelper = TracksDbHelper(this)
|
savingTracksDbHelper = SavingTracksDbHelper(this)
|
||||||
|
|
||||||
if (settings.hasAnyChatToShareLocation() && AndroidUtils.isLocationPermissionAvailable(this)) {
|
if (settings.hasAnyChatToShareLocation() && AndroidUtils.isLocationPermissionAvailable(this)) {
|
||||||
shareLocationHelper.startSharingLocation()
|
shareLocationHelper.startSharingLocation()
|
||||||
|
|
|
@ -0,0 +1,311 @@
|
||||||
|
package net.osmand.telegram.helpers;
|
||||||
|
|
||||||
|
import android.database.Cursor;
|
||||||
|
import android.database.sqlite.SQLiteDatabase;
|
||||||
|
import android.database.sqlite.SQLiteOpenHelper;
|
||||||
|
import android.os.AsyncTask;
|
||||||
|
|
||||||
|
import net.osmand.PlatformUtil;
|
||||||
|
import net.osmand.telegram.TelegramApplication;
|
||||||
|
import net.osmand.telegram.ui.LiveNowTabFragment;
|
||||||
|
import net.osmand.telegram.utils.GPXUtilities;
|
||||||
|
import net.osmand.telegram.utils.GPXUtilities.GPXFile;
|
||||||
|
import net.osmand.telegram.utils.GPXUtilities.Track;
|
||||||
|
import net.osmand.telegram.utils.GPXUtilities.TrkSegment;
|
||||||
|
import net.osmand.telegram.utils.GPXUtilities.WptPt;
|
||||||
|
|
||||||
|
import org.apache.commons.logging.Log;
|
||||||
|
import org.drinkless.td.libcore.telegram.TdApi;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.lang.ref.WeakReference;
|
||||||
|
import java.text.SimpleDateFormat;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Locale;
|
||||||
|
|
||||||
|
public class SavingTracksDbHelper extends SQLiteOpenHelper {
|
||||||
|
|
||||||
|
private final static String DATABASE_NAME = "tracks";
|
||||||
|
private final static int DATABASE_VERSION = 3;
|
||||||
|
|
||||||
|
private final static String TRACK_NAME = "track"; //$NON-NLS-1$
|
||||||
|
private final static String TRACK_COL_USER_ID = "user_id"; //$NON-NLS-1$
|
||||||
|
private final static String TRACK_COL_CHAT_ID = "chat_id"; //$NON-NLS-1$
|
||||||
|
private final static String TRACK_COL_DATE = "date"; //$NON-NLS-1$
|
||||||
|
private final static String TRACK_COL_LAT = "lat"; //$NON-NLS-1$
|
||||||
|
private final static String TRACK_COL_LON = "lon"; //$NON-NLS-1$
|
||||||
|
private final static String TRACK_COL_ALTITUDE = "altitude"; //$NON-NLS-1$
|
||||||
|
private final static String TRACK_COL_SPEED = "speed"; //$NON-NLS-1$
|
||||||
|
private final static String TRACK_COL_HDOP = "hdop"; //$NON-NLS-1$
|
||||||
|
private final static String TRACK_COL_TEXT_INFO = "text_info"; // 1 = true, 0 = false //$NON-NLS-1$
|
||||||
|
|
||||||
|
private final static String INSERT_SCRIPT = "INSERT INTO " + TRACK_NAME + " (" + TRACK_COL_USER_ID + ", " + TRACK_COL_CHAT_ID + ", " + TRACK_COL_LAT + ", " + TRACK_COL_LON + ", "
|
||||||
|
+ TRACK_COL_ALTITUDE + ", " + TRACK_COL_SPEED + ", " + TRACK_COL_HDOP + ", " + TRACK_COL_DATE + ", " + TRACK_COL_TEXT_INFO + ")"
|
||||||
|
+ " VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)";
|
||||||
|
|
||||||
|
private final static String CREATE_SCRIPT = "CREATE TABLE " + TRACK_NAME + " (" + TRACK_COL_USER_ID + " long," + TRACK_COL_CHAT_ID + " long," + TRACK_COL_LAT + " double, " + TRACK_COL_LON + " double, " //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$//$NON-NLS-5$
|
||||||
|
+ TRACK_COL_ALTITUDE + " double, " + TRACK_COL_SPEED + " double, " //$NON-NLS-1$ //$NON-NLS-2$
|
||||||
|
+ TRACK_COL_HDOP + " double, " + TRACK_COL_DATE + " long, " + TRACK_COL_TEXT_INFO + " int )";
|
||||||
|
|
||||||
|
public final static Log log = PlatformUtil.getLog(SavingTracksDbHelper.class);
|
||||||
|
|
||||||
|
private final TelegramApplication app;
|
||||||
|
|
||||||
|
public SavingTracksDbHelper(TelegramApplication app) {
|
||||||
|
super(app, DATABASE_NAME, null, DATABASE_VERSION);
|
||||||
|
this.app = app;
|
||||||
|
|
||||||
|
app.getTelegramHelper().addIncomingMessagesListener(new TelegramHelper.TelegramIncomingMessagesListener() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onReceiveChatLocationMessages(long chatId, @NotNull TdApi.Message... messages) {
|
||||||
|
for (TdApi.Message message : messages) {
|
||||||
|
updateLocationMessage(message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onDeleteChatLocationMessages(long chatId, @NotNull List<? extends TdApi.Message> messages) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void updateLocationMessages() {
|
||||||
|
|
||||||
|
}
|
||||||
|
});
|
||||||
|
app.getTelegramHelper().addOutgoingMessagesListener(new TelegramHelper.TelegramOutgoingMessagesListener() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onUpdateMessages(@NotNull List<? extends TdApi.Message> messages) {
|
||||||
|
for (TdApi.Message message : messages) {
|
||||||
|
updateLocationMessage(message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onDeleteMessages(long chatId, @NotNull List<Long> messages) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onSendLiveLocationError(int code, @NotNull String message) {
|
||||||
|
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onCreate(SQLiteDatabase db) {
|
||||||
|
db.execSQL(CREATE_SCRIPT);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
|
||||||
|
if (oldVersion < 3) {
|
||||||
|
db.execSQL("ALTER TABLE " + TRACK_NAME + " ADD " + TRACK_COL_TEXT_INFO + " int");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void saveAsyncUserDataToGpx(LiveNowTabFragment fragment, File dir, int userId, long interval) {
|
||||||
|
GPXFile gpxFile = app.getSavingTracksDbHelper().collectRecordedDataForUser(userId, interval);
|
||||||
|
if (gpxFile != null && !gpxFile.isEmpty()) {
|
||||||
|
LiveUpdatesPurchaseTask task = new LiveUpdatesPurchaseTask(fragment, gpxFile, dir, userId);
|
||||||
|
task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updateLocationMessage(TdApi.Message message) {
|
||||||
|
TdApi.MessageContent content = message.content;
|
||||||
|
if (content instanceof TdApi.MessageLocation) {
|
||||||
|
long lastTextMessageUpdate = getLastTextTrackPointTimeForUser(message.senderUserId);
|
||||||
|
long currentTime = System.currentTimeMillis();
|
||||||
|
if (lastTextMessageUpdate == 0 || currentTime - lastTextMessageUpdate < 10 * 1000) {
|
||||||
|
log.debug("Add map message" + message.senderUserId);
|
||||||
|
TdApi.MessageLocation messageLocation = (TdApi.MessageLocation) content;
|
||||||
|
insertData(message.senderUserId, message.chatId, messageLocation.location.latitude,
|
||||||
|
messageLocation.location.longitude, 0.0, 0.0, 0.0,
|
||||||
|
Math.max(message.date, message.editDate), 0);
|
||||||
|
} else {
|
||||||
|
log.debug("Skip map message");
|
||||||
|
}
|
||||||
|
} else if (content instanceof TelegramHelper.MessageLocation) {
|
||||||
|
log.debug("Add text message " + message.senderUserId);
|
||||||
|
TelegramHelper.MessageLocation messageLocation = (TelegramHelper.MessageLocation) content;
|
||||||
|
insertData(message.senderUserId, message.chatId, messageLocation.getLat(), messageLocation.getLon(),
|
||||||
|
messageLocation.getAltitude(), messageLocation.getSpeed(), messageLocation.getHdop(),
|
||||||
|
messageLocation.getLastUpdated() * 1000L, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void insertData(int userId, long chatId, double lat, double lon, double alt, double speed, double hdop, long time, int textMessage) {
|
||||||
|
execWithClose(INSERT_SCRIPT, new Object[]{userId, chatId, lat, lon, alt, speed, hdop, time, textMessage});
|
||||||
|
}
|
||||||
|
|
||||||
|
private synchronized void execWithClose(String script, Object[] objects) {
|
||||||
|
SQLiteDatabase db = getWritableDatabase();
|
||||||
|
try {
|
||||||
|
if (db != null) {
|
||||||
|
db.execSQL(script, objects);
|
||||||
|
}
|
||||||
|
} catch (RuntimeException e) {
|
||||||
|
log.error(e.getMessage(), e);
|
||||||
|
} finally {
|
||||||
|
if (db != null) {
|
||||||
|
db.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private long getLastTextTrackPointTimeForUser(int userId) {
|
||||||
|
long res = 0;
|
||||||
|
try {
|
||||||
|
SQLiteDatabase db = getWritableDatabase();
|
||||||
|
if (db != null) {
|
||||||
|
try {
|
||||||
|
Cursor query = db.rawQuery("SELECT " + TRACK_COL_DATE + " FROM " + TRACK_NAME + " WHERE " + TRACK_COL_USER_ID + " = ? AND "
|
||||||
|
+ TRACK_COL_TEXT_INFO + " = ?" + " ORDER BY " + TRACK_COL_DATE + " ASC ", new String[]{String.valueOf(userId), String.valueOf(1)});
|
||||||
|
if (query.moveToFirst()) {
|
||||||
|
res = query.getLong(0);
|
||||||
|
}
|
||||||
|
query.close();
|
||||||
|
} finally {
|
||||||
|
db.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (RuntimeException e) {
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
private GPXFile collectRecordedDataForUser(int userId, long interval) {
|
||||||
|
GPXFile gpxFile = null;
|
||||||
|
SQLiteDatabase db = getReadableDatabase();
|
||||||
|
if (db != null && db.isOpen()) {
|
||||||
|
try {
|
||||||
|
gpxFile = collectDBTracksForUser(db, userId, interval);
|
||||||
|
} finally {
|
||||||
|
db.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return gpxFile;
|
||||||
|
}
|
||||||
|
|
||||||
|
private GPXFile collectDBTracksForUser(SQLiteDatabase db, int userId, long interval) {
|
||||||
|
Cursor query = db.rawQuery("SELECT " + TRACK_COL_USER_ID + "," + TRACK_COL_CHAT_ID + "," + TRACK_COL_LAT + "," + TRACK_COL_LON + "," + TRACK_COL_ALTITUDE + "," //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$
|
||||||
|
+ TRACK_COL_SPEED + "," + TRACK_COL_HDOP + "," + TRACK_COL_DATE + " FROM " + TRACK_NAME +
|
||||||
|
" WHERE " + TRACK_COL_USER_ID + " = ? ORDER BY " + TRACK_COL_DATE + " ASC ", new String[]{String.valueOf(userId)}); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
|
||||||
|
GPXFile gpxFile = new GPXFile();
|
||||||
|
long previousTime = 0;
|
||||||
|
TrkSegment segment = null;
|
||||||
|
Track track = null;
|
||||||
|
if (query.moveToFirst()) {
|
||||||
|
do {
|
||||||
|
long time = query.getLong(7);
|
||||||
|
long curTime = System.currentTimeMillis();
|
||||||
|
if (curTime - time > interval) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
WptPt pt = new WptPt();
|
||||||
|
pt.userId = query.getInt(0);
|
||||||
|
pt.chatId = query.getLong(1);
|
||||||
|
pt.lat = query.getDouble(2);
|
||||||
|
pt.lon = query.getDouble(3);
|
||||||
|
pt.ele = query.getDouble(4);
|
||||||
|
pt.speed = query.getDouble(5);
|
||||||
|
pt.hdop = query.getDouble(6);
|
||||||
|
pt.time = time;
|
||||||
|
long currentInterval = Math.abs(time - previousTime);
|
||||||
|
|
||||||
|
if (track != null) {
|
||||||
|
if (currentInterval < 30 * 60 * 1000) {
|
||||||
|
// 30 minute - same segment
|
||||||
|
segment.points.add(pt);
|
||||||
|
} else {
|
||||||
|
segment = new TrkSegment();
|
||||||
|
segment.points.add(pt);
|
||||||
|
track.segments.add(segment);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
track = new Track();
|
||||||
|
segment = new TrkSegment();
|
||||||
|
track.segments.add(segment);
|
||||||
|
segment.points.add(pt);
|
||||||
|
|
||||||
|
gpxFile.tracks.add(track);
|
||||||
|
}
|
||||||
|
previousTime = time;
|
||||||
|
} while (query.moveToNext());
|
||||||
|
}
|
||||||
|
query.close();
|
||||||
|
return gpxFile;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class LiveUpdatesPurchaseTask extends AsyncTask<Void, Void, List<String>> {
|
||||||
|
|
||||||
|
private TelegramApplication app;
|
||||||
|
private WeakReference<LiveNowTabFragment> fragmentRef;
|
||||||
|
|
||||||
|
private final GPXFile gpxFile;
|
||||||
|
private File dir;
|
||||||
|
private int userId;
|
||||||
|
|
||||||
|
LiveUpdatesPurchaseTask(LiveNowTabFragment fragment, GPXFile gpxFile, File dir, int userId) {
|
||||||
|
this.gpxFile = gpxFile;
|
||||||
|
this.fragmentRef = new WeakReference<>(fragment);
|
||||||
|
this.app = (TelegramApplication) fragment.getActivity().getApplication();
|
||||||
|
this.dir = dir;
|
||||||
|
this.userId = userId;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected List<String> doInBackground(Void... params) {
|
||||||
|
List<String> warnings = new ArrayList<String>();
|
||||||
|
dir.mkdirs();
|
||||||
|
if (dir.getParentFile().canWrite()) {
|
||||||
|
if (dir.exists()) {
|
||||||
|
|
||||||
|
// save file
|
||||||
|
File fout = new File(dir, userId + ".gpx"); //$NON-NLS-1$
|
||||||
|
if (!gpxFile.isEmpty()) {
|
||||||
|
WptPt pt = gpxFile.findPointToShow();
|
||||||
|
|
||||||
|
TdApi.User user = app.getTelegramHelper().getUser(pt.userId);
|
||||||
|
String fileName;
|
||||||
|
if (user != null) {
|
||||||
|
fileName = TelegramUiHelper.INSTANCE.getUserName(user)
|
||||||
|
+ "_" + new SimpleDateFormat("yyyy-MM-dd_HH-mm_EEE", Locale.US).format(new Date(pt.time)); //$NON-NLS-1$
|
||||||
|
} else {
|
||||||
|
fileName = userId + "_" + new SimpleDateFormat("yyyy-MM-dd_HH-mm_EEE", Locale.US).format(new Date(pt.time)); //$NON-NLS-1$
|
||||||
|
}
|
||||||
|
fout = new File(dir, fileName + ".gpx"); //$NON-NLS-1$
|
||||||
|
int ind = 1;
|
||||||
|
while (fout.exists()) {
|
||||||
|
fout = new File(dir, fileName + "_" + (++ind) + ".gpx"); //$NON-NLS-1$ //$NON-NLS-2$
|
||||||
|
}
|
||||||
|
}
|
||||||
|
String warn = GPXUtilities.writeGpxFile(fout, gpxFile, app);
|
||||||
|
if (warn != null) {
|
||||||
|
warnings.add(warn);
|
||||||
|
return warnings;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return warnings;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onPostExecute(List<String> warnings) {
|
||||||
|
if (warnings != null && warnings.isEmpty()) {
|
||||||
|
LiveNowTabFragment fragment = fragmentRef.get();
|
||||||
|
if (fragment != null && fragment.isResumed()) {
|
||||||
|
fragment.shareGpx(gpxFile.path);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -685,6 +685,11 @@ class TelegramHelper private constructor() {
|
||||||
} else if (oldContent is TdApi.MessageLocation && (fromBot || viaBot)) {
|
} else if (oldContent is TdApi.MessageLocation && (fromBot || viaBot)) {
|
||||||
message.content = parseOsmAndBotLocation(message)
|
message.content = parseOsmAndBotLocation(message)
|
||||||
}
|
}
|
||||||
|
if (message.isOutgoing) {
|
||||||
|
outgoingMessagesListeners.forEach {
|
||||||
|
it.onUpdateMessages(listOf(message))
|
||||||
|
}
|
||||||
|
} else {
|
||||||
removeOldMessages(message, fromBot, viaBot)
|
removeOldMessages(message, fromBot, viaBot)
|
||||||
usersLocationMessages[message.id] = message
|
usersLocationMessages[message.id] = message
|
||||||
incomingMessagesListeners.forEach {
|
incomingMessagesListeners.forEach {
|
||||||
|
@ -692,6 +697,7 @@ class TelegramHelper private constructor() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private fun removeOldMessages(newMessage: TdApi.Message, fromBot: Boolean, viaBot: Boolean) {
|
private fun removeOldMessages(newMessage: TdApi.Message, fromBot: Boolean, viaBot: Boolean) {
|
||||||
val iterator = usersLocationMessages.entries.iterator()
|
val iterator = usersLocationMessages.entries.iterator()
|
||||||
|
@ -1145,19 +1151,20 @@ class TelegramHelper private constructor() {
|
||||||
if (isChannelPost) {
|
if (isChannelPost) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
val content = content
|
||||||
|
val isUserTextLocation = (content is TdApi.MessageText) && content.text.text.startsWith(USER_TEXT_LOCATION_TITLE)
|
||||||
val isOsmAndBot = isOsmAndBot(senderUserId) || isOsmAndBot(viaBotUserId)
|
val isOsmAndBot = isOsmAndBot(senderUserId) || isOsmAndBot(viaBotUserId)
|
||||||
if (isOutgoing && !isOsmAndBot) {
|
if (!(isUserTextLocation || content is TdApi.MessageLocation || isOsmAndBot)) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
val lastEdited = Math.max(date, editDate)
|
val lastEdited = Math.max(date, editDate)
|
||||||
if (TimeUnit.MILLISECONDS.toSeconds(System.currentTimeMillis()) - lastEdited > messageActiveTimeSec) {
|
if (TimeUnit.MILLISECONDS.toSeconds(System.currentTimeMillis()) - lastEdited > messageActiveTimeSec) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
val content = content
|
|
||||||
val isUserTextLocation = (content is TdApi.MessageText) && content.text.text.startsWith(USER_TEXT_LOCATION_TITLE)
|
|
||||||
return when (content) {
|
return when (content) {
|
||||||
is TdApi.MessageLocation -> true
|
is TdApi.MessageLocation -> true
|
||||||
is TdApi.MessageText -> (isOsmAndBot) && content.text.text.startsWith(DEVICE_PREFIX) || (isUserTextLocation && senderUserId != currentUser?.id)
|
is TdApi.MessageText -> (isOsmAndBot) && content.text.text.startsWith(DEVICE_PREFIX) || isUserTextLocation
|
||||||
else -> false
|
else -> false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1234,6 +1241,33 @@ class TelegramHelper private constructor() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
s.startsWith(ALTITUDE_PREFIX) -> {
|
||||||
|
val altStr = s.removePrefix(ALTITUDE_PREFIX)
|
||||||
|
try {
|
||||||
|
val alt = altStr.split(" ").first()
|
||||||
|
res.altitude = alt.toDouble()
|
||||||
|
} catch (e: Exception) {
|
||||||
|
e.printStackTrace()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
s.startsWith(SPEED_PREFIX) -> {
|
||||||
|
val altStr = s.removePrefix(SPEED_PREFIX)
|
||||||
|
try {
|
||||||
|
val alt = altStr.split(" ").first()
|
||||||
|
res.speed = alt.toDouble()
|
||||||
|
} catch (e: Exception) {
|
||||||
|
e.printStackTrace()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
s.startsWith(HDOP_PREFIX) -> {
|
||||||
|
val altStr = s.removePrefix(HDOP_PREFIX)
|
||||||
|
try {
|
||||||
|
val alt = altStr.split(" ").first()
|
||||||
|
res.hdop = alt.toDouble()
|
||||||
|
} catch (e: Exception) {
|
||||||
|
e.printStackTrace()
|
||||||
|
}
|
||||||
|
}
|
||||||
s.startsWith(UPDATED_PREFIX) -> {
|
s.startsWith(UPDATED_PREFIX) -> {
|
||||||
if (res.lastUpdated == 0) {
|
if (res.lastUpdated == 0) {
|
||||||
val updatedStr = s.removePrefix(UPDATED_PREFIX)
|
val updatedStr = s.removePrefix(UPDATED_PREFIX)
|
||||||
|
@ -1291,6 +1325,12 @@ class TelegramHelper private constructor() {
|
||||||
internal set
|
internal set
|
||||||
var lastUpdated: Int = 0
|
var lastUpdated: Int = 0
|
||||||
internal set
|
internal set
|
||||||
|
var speed: Double = 0.0
|
||||||
|
internal set
|
||||||
|
var altitude: Double = 0.0
|
||||||
|
internal set
|
||||||
|
var hdop: Double = 0.0
|
||||||
|
internal set
|
||||||
|
|
||||||
override fun getConstructor() = -1
|
override fun getConstructor() = -1
|
||||||
|
|
||||||
|
@ -1510,7 +1550,7 @@ class TelegramHelper private constructor() {
|
||||||
lastTelegramUpdateTime = Math.max(message.date, message.editDate)
|
lastTelegramUpdateTime = Math.max(message.date, message.editDate)
|
||||||
}
|
}
|
||||||
incomingMessagesListeners.forEach {
|
incomingMessagesListeners.forEach {
|
||||||
it.onReceiveChatLocationMessages(message.chatId, message)
|
it.updateLocationMessages()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1536,6 +1576,7 @@ class TelegramHelper private constructor() {
|
||||||
newContent
|
newContent
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
log.debug("UpdateMessageContent " + message.senderUserId)
|
||||||
incomingMessagesListeners.forEach {
|
incomingMessagesListeners.forEach {
|
||||||
it.onReceiveChatLocationMessages(message.chatId, message)
|
it.onReceiveChatLocationMessages(message.chatId, message)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,223 +0,0 @@
|
||||||
package net.osmand.telegram.helpers
|
|
||||||
|
|
||||||
import android.database.sqlite.SQLiteDatabase
|
|
||||||
import android.database.sqlite.SQLiteOpenHelper
|
|
||||||
import android.os.AsyncTask
|
|
||||||
import net.osmand.PlatformUtil
|
|
||||||
import net.osmand.telegram.TelegramApplication
|
|
||||||
import org.drinkless.td.libcore.telegram.TdApi
|
|
||||||
import java.io.File
|
|
||||||
import java.io.FileOutputStream
|
|
||||||
import java.io.IOException
|
|
||||||
|
|
||||||
const val TRACKS_LOG_FILE_NAME = "tracks.txt"
|
|
||||||
|
|
||||||
class TracksDbHelper(val app: TelegramApplication) :
|
|
||||||
SQLiteOpenHelper(app, DATABASE_NAME, null, DATABASE_VERSION) {
|
|
||||||
|
|
||||||
private val tracks = HashSet<Track>()
|
|
||||||
|
|
||||||
private val log = PlatformUtil.getLog(TracksDbHelper::class.java)
|
|
||||||
|
|
||||||
init {
|
|
||||||
app.telegramHelper.addIncomingMessagesListener(object :
|
|
||||||
TelegramHelper.TelegramIncomingMessagesListener {
|
|
||||||
|
|
||||||
override fun onReceiveChatLocationMessages(
|
|
||||||
chatId: Long, vararg messages: TdApi.Message
|
|
||||||
) {
|
|
||||||
messages.forEach { addMessage(chatId, it) }
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onDeleteChatLocationMessages(chatId: Long, messages: List<TdApi.Message>) {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun updateLocationMessages() {}
|
|
||||||
})
|
|
||||||
app.telegramHelper.addOutgoingMessagesListener(object :
|
|
||||||
TelegramHelper.TelegramOutgoingMessagesListener {
|
|
||||||
override fun onUpdateMessages(messages: List<TdApi.Message>) {
|
|
||||||
messages.forEach { addMessage(it.chatId, it) }
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onDeleteMessages(chatId: Long, messages: List<Long>) {
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onSendLiveLocationError(code: Int, message: String) {
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onCreate(db: SQLiteDatabase) {
|
|
||||||
db.execSQL(TRACK_TABLE_CREATE)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onUpgrade(db: SQLiteDatabase, oldVersion: Int, newVersion: Int) {
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun addMessage(chatId: Long, message: TdApi.Message) {
|
|
||||||
log.debug(message)
|
|
||||||
val content = message.content
|
|
||||||
val track = when (content) {
|
|
||||||
is TdApi.MessageLocation ->
|
|
||||||
Track(
|
|
||||||
message.senderUserId,
|
|
||||||
chatId,
|
|
||||||
content.location.latitude,
|
|
||||||
content.location.longitude,
|
|
||||||
0.0,
|
|
||||||
0.0,
|
|
||||||
0.0,
|
|
||||||
Math.max(message.date, message.editDate)
|
|
||||||
)
|
|
||||||
is TelegramHelper.MessageLocation ->
|
|
||||||
Track(
|
|
||||||
message.senderUserId,
|
|
||||||
chatId,
|
|
||||||
content.lat,
|
|
||||||
content.lon,
|
|
||||||
0.0,
|
|
||||||
0.0,
|
|
||||||
0.0,
|
|
||||||
content.lastUpdated
|
|
||||||
)
|
|
||||||
else -> {
|
|
||||||
null
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (track != null) {
|
|
||||||
synchronized(tracks) {
|
|
||||||
tracks.add(track)
|
|
||||||
}
|
|
||||||
insertData(
|
|
||||||
track.userId,
|
|
||||||
track.chatId,
|
|
||||||
track.lat,
|
|
||||||
track.lon,
|
|
||||||
track.altitude,
|
|
||||||
track.speed,
|
|
||||||
track.hdop,
|
|
||||||
track.date
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun insertData(
|
|
||||||
userId: Int,
|
|
||||||
chatId: Long,
|
|
||||||
lat: Double,
|
|
||||||
lon: Double,
|
|
||||||
alt: Double,
|
|
||||||
speed: Double,
|
|
||||||
hdop: Double,
|
|
||||||
time: Int
|
|
||||||
) {
|
|
||||||
execWithClose(UPDATE_SCRIPT, arrayOf(userId, chatId, lat, lon, alt, speed, hdop, time))
|
|
||||||
}
|
|
||||||
|
|
||||||
@Synchronized
|
|
||||||
private fun execWithClose(script: String, objects: Array<Any>) {
|
|
||||||
val db = writableDatabase
|
|
||||||
try {
|
|
||||||
db?.execSQL(script, objects)
|
|
||||||
} catch (e: RuntimeException) {
|
|
||||||
log.error(e.message, e)
|
|
||||||
} finally {
|
|
||||||
db?.close()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
internal fun getTracks(): Set<Track> {
|
|
||||||
val res = HashSet<Track>()
|
|
||||||
readableDatabase?.rawQuery(TRACK_TABLE_SELECT, null)?.apply {
|
|
||||||
if (moveToFirst()) {
|
|
||||||
do {
|
|
||||||
val userId = getInt(0)
|
|
||||||
val chatId = getLong(1)
|
|
||||||
val lat = getDouble(2)
|
|
||||||
val lon = getDouble(3)
|
|
||||||
val altitude = getDouble(4)
|
|
||||||
val speed = getDouble(5)
|
|
||||||
val hdop = getDouble(6)
|
|
||||||
val date = getInt(7)
|
|
||||||
|
|
||||||
val track = Track(userId, chatId, lat, lon, altitude, speed, hdop, date)
|
|
||||||
res.add(track)
|
|
||||||
log.debug(track)
|
|
||||||
} while (moveToNext())
|
|
||||||
}
|
|
||||||
close()
|
|
||||||
}
|
|
||||||
return res
|
|
||||||
}
|
|
||||||
|
|
||||||
companion object {
|
|
||||||
|
|
||||||
private const val DATABASE_NAME = "tracks"
|
|
||||||
private const val DATABASE_VERSION = 1
|
|
||||||
|
|
||||||
private const val TRACK_TABLE_NAME = "track"
|
|
||||||
private const val TRACK_COL_USER_ID = "user_id"
|
|
||||||
private const val TRACK_COL_CHAT_ID = "chat_id"
|
|
||||||
private const val TRACK_COL_DATE = "date"
|
|
||||||
private const val TRACK_COL_LAT = "lat"
|
|
||||||
private const val TRACK_COL_LON = "lon"
|
|
||||||
private const val TRACK_COL_ALTITUDE = "altitude"
|
|
||||||
private const val TRACK_COL_SPEED = "speed"
|
|
||||||
private const val TRACK_COL_HDOP = "hdop"
|
|
||||||
|
|
||||||
private const val TRACK_TABLE_CREATE =
|
|
||||||
"CREATE TABLE $TRACK_TABLE_NAME ($TRACK_COL_USER_ID long, $TRACK_COL_CHAT_ID long, $TRACK_COL_LAT double, $TRACK_COL_LON double, $TRACK_COL_ALTITUDE double, $TRACK_COL_SPEED double, $TRACK_COL_HDOP double, $TRACK_COL_DATE long )"
|
|
||||||
|
|
||||||
private const val UPDATE_SCRIPT =
|
|
||||||
"INSERT INTO $TRACK_TABLE_NAME ($TRACK_COL_USER_ID, $TRACK_COL_CHAT_ID, $TRACK_COL_LAT, $TRACK_COL_LON, $TRACK_COL_ALTITUDE, $TRACK_COL_SPEED, $TRACK_COL_HDOP, $TRACK_COL_DATE) VALUES (?, ?, ?, ?, ?, ?, ?, ?)"
|
|
||||||
|
|
||||||
private const val TRACK_TABLE_SELECT =
|
|
||||||
"SELECT $TRACK_COL_USER_ID, $TRACK_COL_CHAT_ID, $TRACK_COL_LAT, $TRACK_COL_LON, $TRACK_COL_ALTITUDE, $TRACK_COL_SPEED, $TRACK_COL_HDOP, $TRACK_COL_DATE FROM $TRACK_TABLE_NAME"
|
|
||||||
|
|
||||||
private const val TRACK_TABLE_CLEAR = "DELETE FROM $TRACK_TABLE_NAME"
|
|
||||||
}
|
|
||||||
|
|
||||||
data class Track(
|
|
||||||
val userId: Int,
|
|
||||||
val chatId: Long,
|
|
||||||
val lat: Double,
|
|
||||||
val lon: Double,
|
|
||||||
val altitude: Double,
|
|
||||||
val speed: Double,
|
|
||||||
val hdop: Double,
|
|
||||||
val date: Int
|
|
||||||
)
|
|
||||||
|
|
||||||
fun writeToFile() {
|
|
||||||
var text = ""
|
|
||||||
app.tracksDbHelper.getTracks().forEach {
|
|
||||||
text += "\n--------------\n" + it.toString()
|
|
||||||
}
|
|
||||||
val path = app.getExternalFilesDir(null)
|
|
||||||
WriteTracksLogs().executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, text, path.absolutePath)
|
|
||||||
}
|
|
||||||
|
|
||||||
private class WriteTracksLogs : AsyncTask<String, String, Void?>() {
|
|
||||||
|
|
||||||
private val log = PlatformUtil.getLog(WriteTracksLogs::class.java)
|
|
||||||
|
|
||||||
override fun doInBackground(vararg params: String?): Void? {
|
|
||||||
val text = params[0]
|
|
||||||
val path = params[1]
|
|
||||||
if (text != null && path != null) {
|
|
||||||
val file = File(path, TRACKS_LOG_FILE_NAME)
|
|
||||||
val stream = FileOutputStream(file)
|
|
||||||
try {
|
|
||||||
stream.write(text.toByteArray())
|
|
||||||
} catch (e: IOException) {
|
|
||||||
log.error(e)
|
|
||||||
} finally {
|
|
||||||
stream.close()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -33,6 +33,7 @@ import net.osmand.telegram.utils.OsmandFormatter
|
||||||
import net.osmand.telegram.utils.UiUtils.UpdateLocationViewCache
|
import net.osmand.telegram.utils.UiUtils.UpdateLocationViewCache
|
||||||
import net.osmand.util.MapUtils
|
import net.osmand.util.MapUtils
|
||||||
import org.drinkless.td.libcore.telegram.TdApi
|
import org.drinkless.td.libcore.telegram.TdApi
|
||||||
|
import java.io.File
|
||||||
|
|
||||||
private const val CHAT_VIEW_TYPE = 0
|
private const val CHAT_VIEW_TYPE = 0
|
||||||
private const val LOCATION_ITEM_VIEW_TYPE = 1
|
private const val LOCATION_ITEM_VIEW_TYPE = 1
|
||||||
|
@ -232,6 +233,15 @@ class LiveNowTabFragment : Fragment(), TelegramListener, TelegramIncomingMessage
|
||||||
stopLocationUpdate()
|
stopLocationUpdate()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun shareGpx(path: String) {
|
||||||
|
val fileUri = AndroidUtils.getUriForFile(app, File(path))
|
||||||
|
val sendIntent = Intent(Intent.ACTION_SEND)
|
||||||
|
sendIntent.putExtra(Intent.EXTRA_STREAM, fileUri)
|
||||||
|
sendIntent.type = "application/gpx+xml"
|
||||||
|
sendIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
|
||||||
|
startActivity(sendIntent)
|
||||||
|
}
|
||||||
|
|
||||||
private fun chooseOsmAnd() {
|
private fun chooseOsmAnd() {
|
||||||
val ctx = context ?: return
|
val ctx = context ?: return
|
||||||
val installedApps = TelegramSettings.AppConnect.getInstalledApps(ctx)
|
val installedApps = TelegramSettings.AppConnect.getInstalledApps(ctx)
|
||||||
|
@ -446,6 +456,15 @@ class LiveNowTabFragment : Fragment(), TelegramListener, TelegramIncomingMessage
|
||||||
app.showLocationHelper.showLocationOnMap(item, staleLocation)
|
app.showLocationHelper.showLocationOnMap(item, staleLocation)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
openOnMapView?.setOnLongClickListener {
|
||||||
|
app.savingTracksDbHelper.saveAsyncUserDataToGpx(
|
||||||
|
this@LiveNowTabFragment,
|
||||||
|
app.getExternalFilesDir(null),
|
||||||
|
item.userId,
|
||||||
|
60 * 60 * 6 * 1000
|
||||||
|
)
|
||||||
|
true
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
openOnMapView?.setOnClickListener(null)
|
openOnMapView?.setOnClickListener(null)
|
||||||
}
|
}
|
||||||
|
@ -467,7 +486,15 @@ class LiveNowTabFragment : Fragment(), TelegramListener, TelegramIncomingMessage
|
||||||
holder.lastTelegramUpdateTime?.visibility = View.VISIBLE
|
holder.lastTelegramUpdateTime?.visibility = View.VISIBLE
|
||||||
holder.lastTelegramUpdateTime?.text = OsmandFormatter.getListItemLiveTimeDescr(app, telegramHelper.lastTelegramUpdateTime, lastTelegramUpdateStr)
|
holder.lastTelegramUpdateTime?.text = OsmandFormatter.getListItemLiveTimeDescr(app, telegramHelper.lastTelegramUpdateTime, lastTelegramUpdateStr)
|
||||||
holder.lastTelegramUpdateTime?.setOnClickListener {
|
holder.lastTelegramUpdateTime?.setOnClickListener {
|
||||||
app.tracksDbHelper.writeToFile()
|
val currentUserId = telegramHelper.getCurrentUser()?.id
|
||||||
|
if (currentUserId != null) {
|
||||||
|
app.savingTracksDbHelper.saveAsyncUserDataToGpx(
|
||||||
|
this@LiveNowTabFragment,
|
||||||
|
app.getExternalFilesDir(null),
|
||||||
|
currentUserId,
|
||||||
|
60 * 60 * 6 * 1000
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
holder.lastTelegramUpdateTime?.visibility = View.GONE
|
holder.lastTelegramUpdateTime?.visibility = View.GONE
|
||||||
|
|
|
@ -146,8 +146,10 @@ class MyLocationTabFragment : Fragment(), TelegramListener {
|
||||||
mainView.findViewById<TextView>(R.id.status_title).apply {
|
mainView.findViewById<TextView>(R.id.status_title).apply {
|
||||||
val sharingStatus = getString(R.string.sharing_enabled)
|
val sharingStatus = getString(R.string.sharing_enabled)
|
||||||
val spannable = SpannableString(sharingStatus)
|
val spannable = SpannableString(sharingStatus)
|
||||||
spannable.setSpan(ForegroundColorSpan(app.uiUtils.getActiveColor()),
|
spannable.setSpan(
|
||||||
sharingStatus.indexOf(" "), sharingStatus.length, 0)
|
ForegroundColorSpan(app.uiUtils.getActiveColor()),
|
||||||
|
sharingStatus.indexOf(" "), sharingStatus.length, 0
|
||||||
|
)
|
||||||
text = spannable
|
text = spannable
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -450,7 +452,8 @@ class MyLocationTabFragment : Fragment(), TelegramListener {
|
||||||
textContainer.visibility = if (sharingMode) View.GONE else View.VISIBLE
|
textContainer.visibility = if (sharingMode) View.GONE else View.VISIBLE
|
||||||
titleContainer.visibility = if (sharingMode) View.VISIBLE else View.GONE
|
titleContainer.visibility = if (sharingMode) View.VISIBLE else View.GONE
|
||||||
startSharingBtn.visibility = if (sharingMode) View.VISIBLE else View.GONE
|
startSharingBtn.visibility = if (sharingMode) View.VISIBLE else View.GONE
|
||||||
headerParams.scrollFlags = if (sharingMode) 0 else AppBarLayout.LayoutParams.SCROLL_FLAG_SCROLL
|
headerParams.scrollFlags =
|
||||||
|
if (sharingMode) 0 else AppBarLayout.LayoutParams.SCROLL_FLAG_SCROLL
|
||||||
stopSharingSwitcher.isChecked = true
|
stopSharingSwitcher.isChecked = true
|
||||||
appBarScrollRange = -1
|
appBarScrollRange = -1
|
||||||
}
|
}
|
||||||
|
@ -460,7 +463,12 @@ class MyLocationTabFragment : Fragment(), TelegramListener {
|
||||||
settings.updateSharingStatusHistory()
|
settings.updateSharingStatusHistory()
|
||||||
val sharingStatus = settings.sharingStatusChanges.last()
|
val sharingStatus = settings.sharingStatusChanges.last()
|
||||||
sharingStatusTitle.text = sharingStatus.getTitle(app)
|
sharingStatusTitle.text = sharingStatus.getTitle(app)
|
||||||
sharingStatusIcon.setImageDrawable(app.uiUtils.getIcon(sharingStatus.statusType.iconId, sharingStatus.statusType.iconColorRes))
|
sharingStatusIcon.setImageDrawable(
|
||||||
|
app.uiUtils.getIcon(
|
||||||
|
sharingStatus.statusType.iconId,
|
||||||
|
sharingStatus.statusType.iconColorRes
|
||||||
|
)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -490,7 +498,8 @@ class MyLocationTabFragment : Fragment(), TelegramListener {
|
||||||
items.addAll(chats)
|
items.addAll(chats)
|
||||||
if (!sharingMode) {
|
if (!sharingMode) {
|
||||||
for (user in contacts.values) {
|
for (user in contacts.values) {
|
||||||
val containsInChats = chats.any { telegramHelper.getUserIdFromChatType(it.type) == user.id }
|
val containsInChats =
|
||||||
|
chats.any { telegramHelper.getUserIdFromChatType(it.type) == user.id }
|
||||||
if ((!sharingMode && settings.isSharingLocationToUser(user.id)) || user.id == currentUser?.id || containsInChats) {
|
if ((!sharingMode && settings.isSharingLocationToUser(user.id)) || user.id == currentUser?.id || containsInChats) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
@ -521,7 +530,8 @@ class MyLocationTabFragment : Fragment(), TelegramListener {
|
||||||
return list
|
return list
|
||||||
}
|
}
|
||||||
|
|
||||||
inner class MyLocationListAdapter : RecyclerView.Adapter<MyLocationListAdapter.BaseViewHolder>() {
|
inner class MyLocationListAdapter :
|
||||||
|
RecyclerView.Adapter<MyLocationListAdapter.BaseViewHolder>() {
|
||||||
var items = mutableListOf<TdApi.Object>()
|
var items = mutableListOf<TdApi.Object>()
|
||||||
set(value) {
|
set(value) {
|
||||||
field = value
|
field = value
|
||||||
|
@ -569,7 +579,8 @@ class MyLocationTabFragment : Fragment(), TelegramListener {
|
||||||
}
|
}
|
||||||
|
|
||||||
val lastItem = position == itemCount - 1
|
val lastItem = position == itemCount - 1
|
||||||
val placeholderId = if (isChat && telegramHelper.isGroup(item as TdApi.Chat)) R.drawable.img_group_picture else R.drawable.img_user_picture
|
val placeholderId =
|
||||||
|
if (isChat && telegramHelper.isGroup(item as TdApi.Chat)) R.drawable.img_group_picture else R.drawable.img_user_picture
|
||||||
val live = (isChat && settings.isSharingLocationToChat(itemId))
|
val live = (isChat && settings.isSharingLocationToChat(itemId))
|
||||||
val shareInfo = if (isChat) settings.getChatsShareInfo()[itemId] else null
|
val shareInfo = if (isChat) settings.getChatsShareInfo()[itemId] else null
|
||||||
|
|
||||||
|
@ -588,7 +599,12 @@ class MyLocationTabFragment : Fragment(), TelegramListener {
|
||||||
}
|
}
|
||||||
|
|
||||||
holder.title?.text = title
|
holder.title?.text = title
|
||||||
|
holder.icon?.setOnClickListener {
|
||||||
|
app.forceUpdateMyLocation()
|
||||||
|
val curUser = telegramHelper.getCurrentUser()
|
||||||
|
val text = "${curUser?.id} ${curUser?.firstName} ${curUser?.lastName}"
|
||||||
|
Toast.makeText(app, text, Toast.LENGTH_LONG).show()
|
||||||
|
}
|
||||||
if (holder is ChatViewHolder) {
|
if (holder is ChatViewHolder) {
|
||||||
holder.description?.visibility = View.GONE
|
holder.description?.visibility = View.GONE
|
||||||
if (live) {
|
if (live) {
|
||||||
|
@ -648,7 +664,8 @@ class MyLocationTabFragment : Fragment(), TelegramListener {
|
||||||
|
|
||||||
val duration = shareInfo?.userSetLivePeriod
|
val duration = shareInfo?.userSetLivePeriod
|
||||||
if (duration != null && duration > 0) {
|
if (duration != null && duration > 0) {
|
||||||
holder.descriptionDuration?.text = OsmandFormatter.getFormattedDuration(context!!, duration)
|
holder.descriptionDuration?.text =
|
||||||
|
OsmandFormatter.getFormattedDuration(context!!, duration)
|
||||||
holder.description?.apply {
|
holder.description?.apply {
|
||||||
visibility = View.VISIBLE
|
visibility = View.VISIBLE
|
||||||
text = "${getText(R.string.sharing_time)}:"
|
text = "${getText(R.string.sharing_time)}:"
|
||||||
|
@ -658,17 +675,29 @@ class MyLocationTabFragment : Fragment(), TelegramListener {
|
||||||
val expiresIn = shareInfo?.getChatLiveMessageExpireTime() ?: 0
|
val expiresIn = shareInfo?.getChatLiveMessageExpireTime() ?: 0
|
||||||
|
|
||||||
holder.textInArea?.apply {
|
holder.textInArea?.apply {
|
||||||
val time = shareInfo?.additionalActiveTime ?: ADDITIONAL_ACTIVE_TIME_VALUES_SEC[0]
|
val time =
|
||||||
|
shareInfo?.additionalActiveTime ?: ADDITIONAL_ACTIVE_TIME_VALUES_SEC[0]
|
||||||
visibility = View.VISIBLE
|
visibility = View.VISIBLE
|
||||||
text = "+ ${OsmandFormatter.getFormattedDuration(context!!, time)}"
|
text = "+ ${OsmandFormatter.getFormattedDuration(context!!, time)}"
|
||||||
setOnClickListener {
|
setOnClickListener {
|
||||||
val expireTime = shareInfo?.getChatLiveMessageExpireTime() ?: 0
|
val expireTime = shareInfo?.getChatLiveMessageExpireTime() ?: 0
|
||||||
val newLivePeriod = expireTime + (shareInfo?.additionalActiveTime ?: ADDITIONAL_ACTIVE_TIME_VALUES_SEC[0])
|
val newLivePeriod = expireTime + (shareInfo?.additionalActiveTime
|
||||||
val nextAdditionalActiveTime = shareInfo?.getNextAdditionalActiveTime() ?: ADDITIONAL_ACTIVE_TIME_VALUES_SEC[1]
|
?: ADDITIONAL_ACTIVE_TIME_VALUES_SEC[0])
|
||||||
|
val nextAdditionalActiveTime = shareInfo?.getNextAdditionalActiveTime()
|
||||||
|
?: ADDITIONAL_ACTIVE_TIME_VALUES_SEC[1]
|
||||||
if (isChat) {
|
if (isChat) {
|
||||||
settings.shareLocationToChat(itemId, true, newLivePeriod, nextAdditionalActiveTime)
|
settings.shareLocationToChat(
|
||||||
|
itemId,
|
||||||
|
true,
|
||||||
|
newLivePeriod,
|
||||||
|
nextAdditionalActiveTime
|
||||||
|
)
|
||||||
} else {
|
} else {
|
||||||
settings.shareLocationToUser(itemId.toInt(), newLivePeriod, nextAdditionalActiveTime)
|
settings.shareLocationToUser(
|
||||||
|
itemId.toInt(),
|
||||||
|
newLivePeriod,
|
||||||
|
nextAdditionalActiveTime
|
||||||
|
)
|
||||||
}
|
}
|
||||||
notifyItemChanged(position)
|
notifyItemChanged(position)
|
||||||
}
|
}
|
||||||
|
@ -686,13 +715,16 @@ class MyLocationTabFragment : Fragment(), TelegramListener {
|
||||||
|
|
||||||
holder.stopSharingSecondPart?.apply {
|
holder.stopSharingSecondPart?.apply {
|
||||||
visibility = getStopSharingVisibility(expiresIn)
|
visibility = getStopSharingVisibility(expiresIn)
|
||||||
text = "(${getString(R.string.in_time,
|
text = "(${getString(
|
||||||
OsmandFormatter.getFormattedDuration(context!!, expiresIn, true))})"
|
R.string.in_time,
|
||||||
|
OsmandFormatter.getFormattedDuration(context!!, expiresIn, true)
|
||||||
|
)})"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getStopSharingVisibility(expiresIn: Long) = if (expiresIn > 0) View.VISIBLE else View.INVISIBLE
|
private fun getStopSharingVisibility(expiresIn: Long) =
|
||||||
|
if (expiresIn > 0) View.VISIBLE else View.INVISIBLE
|
||||||
|
|
||||||
private fun removeItem(chat: TdApi.Object) {
|
private fun removeItem(chat: TdApi.Object) {
|
||||||
items.remove(chat)
|
items.remove(chat)
|
||||||
|
|
1754
OsmAnd-telegram/src/net/osmand/telegram/utils/GPXUtilities.java
Normal file
1754
OsmAnd-telegram/src/net/osmand/telegram/utils/GPXUtilities.java
Normal file
File diff suppressed because it is too large
Load diff
|
@ -0,0 +1,24 @@
|
||||||
|
package net.osmand.telegram.utils;
|
||||||
|
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*/
|
||||||
|
public interface LocationPoint {
|
||||||
|
|
||||||
|
public double getLatitude();
|
||||||
|
|
||||||
|
public double getLongitude();
|
||||||
|
|
||||||
|
public int getColor();
|
||||||
|
|
||||||
|
public boolean isVisible();
|
||||||
|
|
||||||
|
// public PointDescription getPointDescription(Context ctx);
|
||||||
|
|
||||||
|
// public String getSpeakableName();
|
||||||
|
|
||||||
|
//public void prepareCommandPlayer(CommandBuilder cmd, String names);
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in a new issue