Compare commits
109
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ecce32bfe7 | ||
|
|
ae059dadfe | ||
|
|
2be8c6a11a | ||
|
|
0447c580e4 | ||
|
|
291097e852 | ||
|
|
8c7d103be7 | ||
|
|
427653a796 | ||
|
|
0044771a06 | ||
|
|
9eb0231e1a | ||
|
|
83178cbd6c | ||
|
|
9c0c27d16b | ||
|
|
70d597f6e8 | ||
|
|
990e2f3e09 | ||
|
|
3d4be416d8 | ||
|
|
11d12fc397 | ||
|
|
caf70b72b5 | ||
|
|
f6d860c439 | ||
|
|
7d99f06053 | ||
|
|
b4e260d7cb | ||
|
|
46281102cb | ||
|
|
b237ec034a | ||
|
|
bfae3b5a7d | ||
|
|
5311aa0fb9 | ||
|
|
2dd61e4cce | ||
|
|
63b97d280b | ||
|
|
529d4afb3b | ||
|
|
d2de67bcc3 | ||
|
|
d02d6ceac1 | ||
|
|
4ac4ae03f1 | ||
|
|
4534ed1156 | ||
|
|
c18bdb3abb | ||
|
|
fb524186d1 | ||
|
|
827f10392f | ||
|
|
105f2c76c0 | ||
|
|
2e6617ec83 | ||
|
|
8806f36182 | ||
|
|
07ca91d8a2 | ||
|
|
4443f69056 | ||
|
|
4cc0b04b68 | ||
|
|
89f2e7cf51 | ||
|
|
8b36fea7a5 | ||
|
|
e5848f2f91 | ||
|
|
5448b2f27e | ||
|
|
253b3bdcb9 | ||
|
|
c3a17ca4ca | ||
|
|
4cf7422997 | ||
|
|
270fca127b | ||
|
|
8b614f786d | ||
|
|
415d3fb3a7 | ||
|
|
593086d3b1 | ||
|
|
f3fda343d2 | ||
|
|
6633eb8f60 | ||
|
|
65d66007e0 | ||
|
|
9763f54bf5 | ||
|
|
6be6b5c714 | ||
|
|
f7c4663329 | ||
|
|
03c19bc9cf | ||
|
|
c27410d359 | ||
|
|
00dda2141b | ||
|
|
68c3a1d137 | ||
|
|
e60ab4a54e | ||
|
|
d9d57428ce | ||
|
|
78d30f9546 | ||
|
|
db1b95b15a | ||
|
|
d27c191800 | ||
|
|
682d9bdef1 | ||
|
|
6f3565a4e3 | ||
|
|
a7e70dabe5 | ||
|
|
d602766fc4 | ||
|
|
5c95ae3dd0 | ||
|
|
0e354123fc | ||
|
|
db51fb01c0 | ||
|
|
cfdf283457 | ||
|
|
724e8b9308 | ||
|
|
46a05c916c | ||
|
|
c814a1b384 | ||
|
|
d1eed0fbd5 | ||
|
|
6faa7dbb74 | ||
|
|
57e8c32629 | ||
|
|
9b6425442a | ||
|
|
025f582f6a | ||
|
|
2dec7b28f4 | ||
|
|
30886adc62 | ||
|
|
761d32dab6 | ||
|
|
7dbebc1cd1 | ||
|
|
dd6c793979 | ||
|
|
c441823d94 | ||
|
|
090c82dd40 | ||
|
|
a7a5a3cd4c | ||
|
|
0e36807bd6 | ||
|
|
24c41e5a6d | ||
|
|
22e12b6422 | ||
|
|
0efdefb207 | ||
|
|
80d2045fbb | ||
|
|
7bb0d69a96 | ||
|
|
96d71394fd | ||
|
|
371f9ae4a6 | ||
|
|
b439165246 | ||
|
|
07eefdcea9 | ||
|
|
9d8533e066 | ||
|
|
37f39f29ab | ||
|
|
84d2d583a3 | ||
|
|
f2c73c6ede | ||
|
|
59e92e30f2 | ||
|
|
be1bc8efbb | ||
|
|
ac0206f5ab | ||
|
|
e576fa0be5 | ||
|
|
9fc5aa4fc3 | ||
|
|
f6555f49d8 |
@@ -59,7 +59,7 @@
|
|||||||
* Возможность отключить рекомендации от ВК
|
* Возможность отключить рекомендации от ВК
|
||||||
* Редактор докбара
|
* Редактор докбара
|
||||||
* Редактор элементов Superapp
|
* Редактор элементов Superapp
|
||||||
* Медиа контент
|
* Медиаконтент
|
||||||
* Округление дат
|
* Округление дат
|
||||||
* 1 января в 4:20
|
* 1 января в 4:20
|
||||||
* 1 января в 4:20:00
|
* 1 января в 4:20:00
|
||||||
@@ -72,6 +72,7 @@
|
|||||||
* Возможность скачивать видео, очищать историю просмотра видео
|
* Возможность скачивать видео, очищать историю просмотра видео
|
||||||
* Возможность найти фотографию через поисковые системы
|
* Возможность найти фотографию через поисковые системы
|
||||||
* Интеграция с <a href="https://vkx.app/">VK X</a>
|
* Интеграция с <a href="https://vkx.app/">VK X</a>
|
||||||
|
* Возможность кешировать треки в приложении
|
||||||
* Сообщения
|
* Сообщения
|
||||||
* Обои в сообщениях
|
* Обои в сообщениях
|
||||||
* Возможность выключения кнопки записи голосовых сообщений
|
* Возможность выключения кнопки записи голосовых сообщений
|
||||||
@@ -84,6 +85,7 @@
|
|||||||
* Альтернативный дизайн эмодзи меню
|
* Альтернативный дизайн эмодзи меню
|
||||||
* Возможность использовать системные эмодзи
|
* Возможность использовать системные эмодзи
|
||||||
* Возможнсть использовать Enter с аппаратной клавиатуры
|
* Возможнсть использовать Enter с аппаратной клавиатуры
|
||||||
|
* Панель ввода из приложения ВК для IOS
|
||||||
* Активность
|
* Активность
|
||||||
* Возможность видеть удаленные сообщения
|
* Возможность видеть удаленные сообщения
|
||||||
* Функционал, позволяющий оставаться в «оффлайне» (принудительный оффлайн/не отправлять статус онлайна и т.п.)
|
* Функционал, позволяющий оставаться в «оффлайне» (принудительный оффлайн/не отправлять статус онлайна и т.п.)
|
||||||
|
|||||||
+4
-2
@@ -77,10 +77,11 @@ android {
|
|||||||
targetSdkVersion 32
|
targetSdkVersion 32
|
||||||
versionCode 1
|
versionCode 1
|
||||||
versionName "1.0"
|
versionName "1.0"
|
||||||
multiDexEnabled false
|
multiDexEnabled true
|
||||||
}
|
}
|
||||||
|
|
||||||
compileOptions {
|
compileOptions {
|
||||||
|
coreLibraryDesugaringEnabled true
|
||||||
sourceCompatibility JavaVersion.VERSION_11
|
sourceCompatibility JavaVersion.VERSION_11
|
||||||
targetCompatibility JavaVersion.VERSION_11
|
targetCompatibility JavaVersion.VERSION_11
|
||||||
}
|
}
|
||||||
@@ -88,8 +89,9 @@ android {
|
|||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
|
coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:1.1.5'
|
||||||
|
implementation 'net.sourceforge.streamsupport:streamsupport-minifuture:1.7.4'
|
||||||
implementation 'com.google.android.material:material:1.6.1'
|
implementation 'com.google.android.material:material:1.6.1'
|
||||||
implementation 'androidx.exifinterface:exifinterface:1.3.3'
|
|
||||||
implementation 'androidx.preference:preference:1.2.0'
|
implementation 'androidx.preference:preference:1.2.0'
|
||||||
implementation fileTree(dir: 'libs', include: ['*.aar'])
|
implementation fileTree(dir: 'libs', include: ['*.aar'])
|
||||||
compileOnly fileTree(dir: 'libs', include: ['*.jar'])
|
compileOnly fileTree(dir: 'libs', include: ['*.jar'])
|
||||||
|
|||||||
@@ -0,0 +1,33 @@
|
|||||||
|
// IVKExternalMusic.aidl
|
||||||
|
package bruhcollective.itaysonlab.libvkx;
|
||||||
|
|
||||||
|
interface ILibVkxService {
|
||||||
|
// Starts playback. playbackContext can be "other" if you don't sure what it is
|
||||||
|
void play(in List<String> audio_ids, in int index, in String playbackContext) = 1;
|
||||||
|
|
||||||
|
// A UserID. CHECK FOR THIS TO BE EQUAL BEFORE SENDING ANYTHING TO SERVICE!
|
||||||
|
int getUserId() = 2;
|
||||||
|
|
||||||
|
// Cache add/remove
|
||||||
|
void addTrackToCache(in int track_id, in int owner_id, in String access_key) = 3;
|
||||||
|
void deleteTrackFromCache(in int track_id, in int owner_id) = 4;
|
||||||
|
boolean isTrackCached(in int track_id, in int owner_id) = 5;
|
||||||
|
|
||||||
|
// Get a list of cached tracks. The response is close to VK's original response (an audio list)
|
||||||
|
// Also, the items in the list are JSON ones.
|
||||||
|
List<String> getCache() = 6;
|
||||||
|
|
||||||
|
// [ver 1.1]
|
||||||
|
void downloadTrack(in int track_id, in int owner_id, in String access_key) = 7;
|
||||||
|
void downloadPlaylist(in int playlist_id, in int owner_id, in String access_key) = 8;
|
||||||
|
void addPlaylistToCache(in int playlist_id, in int owner_id, in String access_key) = 9;
|
||||||
|
void deletePlaylistFromCache(in int playlist_id, in int owner_id) = 10;
|
||||||
|
|
||||||
|
// [ver 1.2]
|
||||||
|
String getCacheCatalog() = 11;
|
||||||
|
List<String> getTracksInPlaylist(in String playlist_id, in String owner_id) = 12;
|
||||||
|
String getPlaylistDefJson(in String playlist_id, in String owner_id) = 13;
|
||||||
|
|
||||||
|
// [ver 1.3]
|
||||||
|
boolean isPlaylistCached(in int playlist_id, in int owner_id) = 14;
|
||||||
|
}
|
||||||
@@ -1,340 +0,0 @@
|
|||||||
/*
|
|
||||||
* This file is auto-generated. DO NOT MODIFY.
|
|
||||||
*/
|
|
||||||
package bruhcollective.itaysonlab.libvkx;
|
|
||||||
|
|
||||||
// Works only with original signature of VT
|
|
||||||
|
|
||||||
public interface ILibVkxService extends android.os.IInterface {
|
|
||||||
void play(java.util.List<String> audio_ids, int index, String playbackContext) throws android.os.RemoteException;
|
|
||||||
|
|
||||||
int getUserId() throws android.os.RemoteException;
|
|
||||||
// Starts playback. playbackContext can be "other" if you don't sure what it is
|
|
||||||
|
|
||||||
void addTrackToCache(int track_id, int owner_id, String access_key) throws android.os.RemoteException;
|
|
||||||
// A UserID. CHECK FOR THIS TO BE EQUAL BEFORE SENDING ANYTHING TO SERVICE!
|
|
||||||
|
|
||||||
void deleteTrackFromCache(int track_id, int owner_id) throws android.os.RemoteException;
|
|
||||||
// Cache add/remove
|
|
||||||
|
|
||||||
boolean isTrackCached(int track_id, int owner_id) throws android.os.RemoteException;
|
|
||||||
|
|
||||||
java.util.List<String> getCache() throws android.os.RemoteException;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Default implementation for ILibVkxService.
|
|
||||||
*/
|
|
||||||
class Default implements ILibVkxService {
|
|
||||||
// Starts playback. playbackContext can be "other" if you don't sure what it is
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void play(java.util.List<String> audio_ids, int index, String playbackContext) throws android.os.RemoteException {
|
|
||||||
}
|
|
||||||
// A UserID. CHECK FOR THIS TO BE EQUAL BEFORE SENDING ANYTHING TO SERVICE!
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int getUserId() throws android.os.RemoteException {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
// Cache add/remove
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void addTrackToCache(int track_id, int owner_id, String access_key) throws android.os.RemoteException {
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void deleteTrackFromCache(int track_id, int owner_id) throws android.os.RemoteException {
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isTrackCached(int track_id, int owner_id) throws android.os.RemoteException {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
// Get a list of cached tracks. The response is close to VK's original response (an audio list)
|
|
||||||
// Also, the items in the list are JSON ones.
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public java.util.List<String> getCache() throws android.os.RemoteException {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public android.os.IBinder asBinder() {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Get a list of cached tracks. The response is close to VK's original response (an audio list)
|
|
||||||
// Also, the items in the list are JSON ones.
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Local-side IPC implementation stub class.
|
|
||||||
*/
|
|
||||||
abstract class Stub extends android.os.Binder implements ILibVkxService {
|
|
||||||
static final int TRANSACTION_play = (android.os.IBinder.FIRST_CALL_TRANSACTION + 1);
|
|
||||||
static final int TRANSACTION_getUserId = (android.os.IBinder.FIRST_CALL_TRANSACTION + 2);
|
|
||||||
static final int TRANSACTION_addTrackToCache = (android.os.IBinder.FIRST_CALL_TRANSACTION + 3);
|
|
||||||
static final int TRANSACTION_deleteTrackFromCache = (android.os.IBinder.FIRST_CALL_TRANSACTION + 4);
|
|
||||||
static final int TRANSACTION_isTrackCached = (android.os.IBinder.FIRST_CALL_TRANSACTION + 5);
|
|
||||||
static final int TRANSACTION_getCache = (android.os.IBinder.FIRST_CALL_TRANSACTION + 6);
|
|
||||||
private static final String DESCRIPTOR = "bruhcollective.itaysonlab.libvkx.ILibVkxService";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Construct the stub at attach it to the interface.
|
|
||||||
*/
|
|
||||||
public Stub() {
|
|
||||||
this.attachInterface(this, DESCRIPTOR);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Cast an IBinder object into an bruhcollective.itaysonlab.libvkx.ILibVkxService interface,
|
|
||||||
* generating a proxy if needed.
|
|
||||||
*/
|
|
||||||
public static ILibVkxService asInterface(android.os.IBinder obj) {
|
|
||||||
if ((obj == null)) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
|
|
||||||
if (((iin != null) && (iin instanceof ILibVkxService))) {
|
|
||||||
return ((ILibVkxService) iin);
|
|
||||||
}
|
|
||||||
return new Proxy(obj);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static boolean setDefaultImpl(ILibVkxService impl) {
|
|
||||||
if (Proxy.sDefaultImpl == null && impl != null) {
|
|
||||||
Proxy.sDefaultImpl = impl;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static ILibVkxService getDefaultImpl() {
|
|
||||||
return Proxy.sDefaultImpl;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public android.os.IBinder asBinder() {
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags) throws android.os.RemoteException {
|
|
||||||
String descriptor = DESCRIPTOR;
|
|
||||||
switch (code) {
|
|
||||||
case INTERFACE_TRANSACTION: {
|
|
||||||
reply.writeString(descriptor);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
case TRANSACTION_play: {
|
|
||||||
data.enforceInterface(descriptor);
|
|
||||||
java.util.List<String> _arg0;
|
|
||||||
_arg0 = data.createStringArrayList();
|
|
||||||
int _arg1;
|
|
||||||
_arg1 = data.readInt();
|
|
||||||
String _arg2;
|
|
||||||
_arg2 = data.readString();
|
|
||||||
this.play(_arg0, _arg1, _arg2);
|
|
||||||
reply.writeNoException();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
case TRANSACTION_getUserId: {
|
|
||||||
data.enforceInterface(descriptor);
|
|
||||||
int _result = this.getUserId();
|
|
||||||
reply.writeNoException();
|
|
||||||
reply.writeInt(_result);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
case TRANSACTION_addTrackToCache: {
|
|
||||||
data.enforceInterface(descriptor);
|
|
||||||
int _arg0;
|
|
||||||
_arg0 = data.readInt();
|
|
||||||
int _arg1;
|
|
||||||
_arg1 = data.readInt();
|
|
||||||
String _arg2;
|
|
||||||
_arg2 = data.readString();
|
|
||||||
this.addTrackToCache(_arg0, _arg1, _arg2);
|
|
||||||
reply.writeNoException();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
case TRANSACTION_deleteTrackFromCache: {
|
|
||||||
data.enforceInterface(descriptor);
|
|
||||||
int _arg0;
|
|
||||||
_arg0 = data.readInt();
|
|
||||||
int _arg1;
|
|
||||||
_arg1 = data.readInt();
|
|
||||||
this.deleteTrackFromCache(_arg0, _arg1);
|
|
||||||
reply.writeNoException();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
case TRANSACTION_isTrackCached: {
|
|
||||||
data.enforceInterface(descriptor);
|
|
||||||
int _arg0;
|
|
||||||
_arg0 = data.readInt();
|
|
||||||
int _arg1;
|
|
||||||
_arg1 = data.readInt();
|
|
||||||
boolean _result = this.isTrackCached(_arg0, _arg1);
|
|
||||||
reply.writeNoException();
|
|
||||||
reply.writeInt(((_result) ? (1) : (0)));
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
case TRANSACTION_getCache: {
|
|
||||||
data.enforceInterface(descriptor);
|
|
||||||
java.util.List<String> _result = this.getCache();
|
|
||||||
reply.writeNoException();
|
|
||||||
reply.writeStringList(_result);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
default: {
|
|
||||||
return super.onTransact(code, data, reply, flags);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static class Proxy implements ILibVkxService {
|
|
||||||
public static ILibVkxService sDefaultImpl;
|
|
||||||
private final android.os.IBinder mRemote;
|
|
||||||
|
|
||||||
Proxy(android.os.IBinder remote) {
|
|
||||||
mRemote = remote;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public android.os.IBinder asBinder() {
|
|
||||||
return mRemote;
|
|
||||||
}
|
|
||||||
// Starts playback. playbackContext can be "other" if you don't sure what it is
|
|
||||||
|
|
||||||
public String getInterfaceDescriptor() {
|
|
||||||
return DESCRIPTOR;
|
|
||||||
}
|
|
||||||
// A UserID. CHECK FOR THIS TO BE EQUAL BEFORE SENDING ANYTHING TO SERVICE!
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void play(java.util.List<String> audio_ids, int index, String playbackContext) throws android.os.RemoteException {
|
|
||||||
android.os.Parcel _data = android.os.Parcel.obtain();
|
|
||||||
android.os.Parcel _reply = android.os.Parcel.obtain();
|
|
||||||
try {
|
|
||||||
_data.writeInterfaceToken(DESCRIPTOR);
|
|
||||||
_data.writeStringList(audio_ids);
|
|
||||||
_data.writeInt(index);
|
|
||||||
_data.writeString(playbackContext);
|
|
||||||
boolean _status = mRemote.transact(Stub.TRANSACTION_play, _data, _reply, 0);
|
|
||||||
if (!_status && getDefaultImpl() != null) {
|
|
||||||
getDefaultImpl().play(audio_ids, index, playbackContext);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
_reply.readException();
|
|
||||||
} finally {
|
|
||||||
_reply.recycle();
|
|
||||||
_data.recycle();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Cache add/remove
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int getUserId() throws android.os.RemoteException {
|
|
||||||
android.os.Parcel _data = android.os.Parcel.obtain();
|
|
||||||
android.os.Parcel _reply = android.os.Parcel.obtain();
|
|
||||||
int _result;
|
|
||||||
try {
|
|
||||||
_data.writeInterfaceToken(DESCRIPTOR);
|
|
||||||
boolean _status = mRemote.transact(Stub.TRANSACTION_getUserId, _data, _reply, 0);
|
|
||||||
if (!_status && getDefaultImpl() != null) {
|
|
||||||
return getDefaultImpl().getUserId();
|
|
||||||
}
|
|
||||||
_reply.readException();
|
|
||||||
_result = _reply.readInt();
|
|
||||||
} finally {
|
|
||||||
_reply.recycle();
|
|
||||||
_data.recycle();
|
|
||||||
}
|
|
||||||
return _result;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void addTrackToCache(int track_id, int owner_id, String access_key) throws android.os.RemoteException {
|
|
||||||
android.os.Parcel _data = android.os.Parcel.obtain();
|
|
||||||
android.os.Parcel _reply = android.os.Parcel.obtain();
|
|
||||||
try {
|
|
||||||
_data.writeInterfaceToken(DESCRIPTOR);
|
|
||||||
_data.writeInt(track_id);
|
|
||||||
_data.writeInt(owner_id);
|
|
||||||
_data.writeString(access_key);
|
|
||||||
boolean _status = mRemote.transact(Stub.TRANSACTION_addTrackToCache, _data, _reply, 0);
|
|
||||||
if (!_status && getDefaultImpl() != null) {
|
|
||||||
getDefaultImpl().addTrackToCache(track_id, owner_id, access_key);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
_reply.readException();
|
|
||||||
} finally {
|
|
||||||
_reply.recycle();
|
|
||||||
_data.recycle();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void deleteTrackFromCache(int track_id, int owner_id) throws android.os.RemoteException {
|
|
||||||
android.os.Parcel _data = android.os.Parcel.obtain();
|
|
||||||
android.os.Parcel _reply = android.os.Parcel.obtain();
|
|
||||||
try {
|
|
||||||
_data.writeInterfaceToken(DESCRIPTOR);
|
|
||||||
_data.writeInt(track_id);
|
|
||||||
_data.writeInt(owner_id);
|
|
||||||
boolean _status = mRemote.transact(Stub.TRANSACTION_deleteTrackFromCache, _data, _reply, 0);
|
|
||||||
if (!_status && getDefaultImpl() != null) {
|
|
||||||
getDefaultImpl().deleteTrackFromCache(track_id, owner_id);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
_reply.readException();
|
|
||||||
} finally {
|
|
||||||
_reply.recycle();
|
|
||||||
_data.recycle();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Get a list of cached tracks. The response is close to VK's original response (an audio list)
|
|
||||||
// Also, the items in the list are JSON ones.
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isTrackCached(int track_id, int owner_id) throws android.os.RemoteException {
|
|
||||||
android.os.Parcel _data = android.os.Parcel.obtain();
|
|
||||||
android.os.Parcel _reply = android.os.Parcel.obtain();
|
|
||||||
boolean _result;
|
|
||||||
try {
|
|
||||||
_data.writeInterfaceToken(DESCRIPTOR);
|
|
||||||
_data.writeInt(track_id);
|
|
||||||
_data.writeInt(owner_id);
|
|
||||||
boolean _status = mRemote.transact(Stub.TRANSACTION_isTrackCached, _data, _reply, 0);
|
|
||||||
if (!_status && getDefaultImpl() != null) {
|
|
||||||
return getDefaultImpl().isTrackCached(track_id, owner_id);
|
|
||||||
}
|
|
||||||
_reply.readException();
|
|
||||||
_result = (0 != _reply.readInt());
|
|
||||||
} finally {
|
|
||||||
_reply.recycle();
|
|
||||||
_data.recycle();
|
|
||||||
}
|
|
||||||
return _result;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public java.util.List<String> getCache() throws android.os.RemoteException {
|
|
||||||
android.os.Parcel _data = android.os.Parcel.obtain();
|
|
||||||
android.os.Parcel _reply = android.os.Parcel.obtain();
|
|
||||||
java.util.List<String> _result;
|
|
||||||
try {
|
|
||||||
_data.writeInterfaceToken(DESCRIPTOR);
|
|
||||||
boolean _status = mRemote.transact(Stub.TRANSACTION_getCache, _data, _reply, 0);
|
|
||||||
if (!_status && getDefaultImpl() != null) {
|
|
||||||
return getDefaultImpl().getCache();
|
|
||||||
}
|
|
||||||
_reply.readException();
|
|
||||||
_result = _reply.createStringArrayList();
|
|
||||||
} finally {
|
|
||||||
_reply.recycle();
|
|
||||||
_data.recycle();
|
|
||||||
}
|
|
||||||
return _result;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -81,11 +81,11 @@ public class LibVKXClient {
|
|||||||
lambdaplay(list, musicTrack, iLibVkxService, null);
|
lambdaplay(list, musicTrack, iLibVkxService, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static String asId(MusicTrack musicTrack) {
|
public static String asId(MusicTrack musicTrack) {
|
||||||
String str = musicTrack.e + "_" + musicTrack.d;
|
String id = musicTrack.e + "_" + musicTrack.d;
|
||||||
if (musicTrack.O == null || musicTrack.O.equals("")) {
|
if (musicTrack.O != null && !musicTrack.O.equals("")) {
|
||||||
return str;
|
id += "_" + musicTrack.O;
|
||||||
}
|
}
|
||||||
return str + "_" + musicTrack.O;
|
return id;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,58 +1,22 @@
|
|||||||
package ru.vtosters.lite.deviceinfo;
|
package ru.vtosters.lite.deviceinfo;
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
import static ru.vtosters.lite.utils.About.getBuildNumber;
|
||||||
|
|
||||||
public class Device {
|
public class Device {
|
||||||
private String androidId;
|
|
||||||
private String bluetoothMac;
|
|
||||||
private String boardName;
|
private String boardName;
|
||||||
private String brandName;
|
private String brandName;
|
||||||
private String cpuAbi;
|
|
||||||
private String deviceName;
|
private String deviceName;
|
||||||
private String firmwareDisplay;
|
|
||||||
private String firmwareId;
|
|
||||||
private String manufacturerName;
|
private String manufacturerName;
|
||||||
private String modelName;
|
private String modelName;
|
||||||
private String productName;
|
private String productName;
|
||||||
private int sdkVersion;
|
private int sdkVersion;
|
||||||
private String serialId;
|
|
||||||
private String wifiMac;
|
|
||||||
|
|
||||||
public Device withSerialId(String str) {
|
|
||||||
this.serialId = str;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Device withAndroidId(String str) {
|
|
||||||
this.androidId = str;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Device withWifiMac(String str) {
|
|
||||||
this.wifiMac = str;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Device withBluetoothMac(String str) {
|
|
||||||
this.bluetoothMac = str;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Device withSdkVersion(int i) {
|
public Device withSdkVersion(int i) {
|
||||||
this.sdkVersion = i;
|
this.sdkVersion = i;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Device withFirmwareId(String str) {
|
|
||||||
this.firmwareId = str;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Device withFirmwareDisplay(String str) {
|
|
||||||
this.firmwareDisplay = str;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Device withProductName(String str) {
|
public Device withProductName(String str) {
|
||||||
this.productName = str;
|
this.productName = str;
|
||||||
return this;
|
return this;
|
||||||
@@ -68,11 +32,6 @@ public class Device {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Device withCpuAbi(String str) {
|
|
||||||
this.cpuAbi = str;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Device withManufacturerName(String str) {
|
public Device withManufacturerName(String str) {
|
||||||
this.manufacturerName = str;
|
this.manufacturerName = str;
|
||||||
return this;
|
return this;
|
||||||
@@ -88,12 +47,7 @@ public class Device {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@NonNull
|
|
||||||
public String toString() {
|
|
||||||
return "Device{serialId='" + this.serialId + "', androidId='" + this.androidId + "', wifiMac='" + this.wifiMac + "', bluetoothMac='" + this.bluetoothMac + "'}";
|
|
||||||
}
|
|
||||||
|
|
||||||
public String toDeviceName() {
|
public String toDeviceName() {
|
||||||
return "Device{sdkVersion=" + this.sdkVersion + ", productName='" + this.productName + "', deviceName='" + this.deviceName + "', boardName='" + this.boardName + "', cpuAbi='" + this.cpuAbi + "', manufacturerName='" + this.manufacturerName + "', brandName='" + this.brandName + "', modelName='" + this.modelName + "'}";
|
return "Device information: " + "commit='" + getBuildNumber() + "', sdkVersion=" + this.sdkVersion + ", productName='" + this.productName + "', deviceName='" + this.deviceName + "', boardName='" + this.boardName + "', manufacturerName='" + this.manufacturerName + "', brandName='" + this.brandName + "', modelName='" + this.modelName + "'";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,195 +1,11 @@
|
|||||||
package ru.vtosters.lite.deviceinfo;
|
package ru.vtosters.lite.deviceinfo;
|
||||||
|
|
||||||
import android.annotation.SuppressLint;
|
|
||||||
import android.bluetooth.BluetoothAdapter;
|
|
||||||
import android.content.Context;
|
|
||||||
import android.net.wifi.WifiInfo;
|
|
||||||
import android.net.wifi.WifiManager;
|
|
||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
import android.provider.Settings;
|
|
||||||
import android.text.TextUtils;
|
|
||||||
import android.util.Log;
|
|
||||||
|
|
||||||
import androidx.core.os.EnvironmentCompat;
|
|
||||||
|
|
||||||
import java.io.BufferedReader;
|
|
||||||
import java.io.FileReader;
|
|
||||||
import java.lang.reflect.Field;
|
|
||||||
import java.lang.reflect.Method;
|
|
||||||
import java.net.NetworkInterface;
|
|
||||||
import java.util.Collections;
|
|
||||||
|
|
||||||
public class DeviceInfoCollector {
|
public class DeviceInfoCollector {
|
||||||
private static final String TAG = "DeviceInfoCollector";
|
|
||||||
|
|
||||||
public Device collect(Context context) {
|
public Device collect() {
|
||||||
return new Device().withSerialId(serialId()).withAndroidId(androidId(context)).withWifiMac(wifiMac(context)).withBluetoothMac(bluetoothMac(context)).withSdkVersion(Build.VERSION.SDK_INT).withFirmwareId(Build.ID).withFirmwareDisplay(Build.DISPLAY).withProductName(Build.PRODUCT).withDeviceName(Build.DEVICE).withBoardName(Build.BOARD).withCpuAbi(Build.CPU_ABI).withManufacturerName(Build.MANUFACTURER).withBrandName(Build.BRAND).withModelName(Build.MODEL);
|
return new Device().withSdkVersion(Build.VERSION.SDK_INT).withProductName(Build.PRODUCT).withDeviceName(Build.DEVICE).withBoardName(Build.BOARD).withManufacturerName(Build.MANUFACTURER).withBrandName(Build.BRAND).withModelName(Build.MODEL);
|
||||||
}
|
|
||||||
|
|
||||||
private String serialId() {
|
|
||||||
String str;
|
|
||||||
try {
|
|
||||||
@SuppressLint("PrivateApi")
|
|
||||||
Class<?> cls = Class.forName("android.os.SystemProperties");
|
|
||||||
Method method = cls.getMethod("get", String.class);
|
|
||||||
str = (String) method.invoke(cls, "gsm.sn1");
|
|
||||||
if (isInvalidSerial(str)) {
|
|
||||||
str = (String) method.invoke(cls, "ril.serialnumber");
|
|
||||||
}
|
|
||||||
if (isInvalidSerial(str)) {
|
|
||||||
str = (String) method.invoke(cls, "ro.serialno");
|
|
||||||
}
|
|
||||||
if (isInvalidSerial(str)) {
|
|
||||||
str = (String) method.invoke(cls, "sys.serialnumber");
|
|
||||||
}
|
|
||||||
if (isInvalidSerial(str)) {
|
|
||||||
str = Build.SERIAL;
|
|
||||||
}
|
|
||||||
} catch (Exception e) {
|
|
||||||
Log.d(TAG, "Serial ID obtaining failed: ", e);
|
|
||||||
}
|
|
||||||
str = null;
|
|
||||||
if (str != null) {
|
|
||||||
return str.toLowerCase();
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressLint("HardwareIds")
|
|
||||||
private String androidId(Context context) {
|
|
||||||
return Settings.Secure.getString(context.getContentResolver(), "android_id").toLowerCase();
|
|
||||||
}
|
|
||||||
|
|
||||||
private String wifiMac(Context context) {
|
|
||||||
String wifiMacFromManager = wifiMacFromManager(context);
|
|
||||||
if (isInvalidMac(wifiMacFromManager)) {
|
|
||||||
wifiMacFromManager = wifiMacFromNetworkInterfaces();
|
|
||||||
}
|
|
||||||
if (isInvalidMac(wifiMacFromManager)) {
|
|
||||||
wifiMacFromManager = wifiMacFromFileSystem();
|
|
||||||
}
|
|
||||||
if (isInvalidMac(wifiMacFromManager)) {
|
|
||||||
wifiMacFromManager = null;
|
|
||||||
}
|
|
||||||
if (wifiMacFromManager != null) {
|
|
||||||
return wifiMacFromManager.toLowerCase();
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
private String wifiMacFromManager(Context context) {
|
|
||||||
WifiInfo connectionInfo;
|
|
||||||
try {
|
|
||||||
WifiManager wifiManager = (WifiManager) context.getApplicationContext().getSystemService(Context.WIFI_SERVICE);
|
|
||||||
if (wifiManager == null || (connectionInfo = wifiManager.getConnectionInfo()) == null) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
} catch (Exception e) {
|
|
||||||
Log.d(TAG, "WiFi MAC obtaining from manager failed: ", e);
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private String wifiMacFromNetworkInterfaces() {
|
|
||||||
try {
|
|
||||||
for (NetworkInterface networkInterface : Collections.list(NetworkInterface.getNetworkInterfaces())) {
|
|
||||||
if ("wlan0".equalsIgnoreCase(networkInterface.getName())) {
|
|
||||||
byte[] hardwareAddress = networkInterface.getHardwareAddress();
|
|
||||||
if (hardwareAddress == null) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
StringBuilder sb = new StringBuilder();
|
|
||||||
int length = hardwareAddress.length;
|
|
||||||
for (int i = 0; i < length; i++) {
|
|
||||||
sb.append(String.format("%02X:", hardwareAddress[i]));
|
|
||||||
}
|
|
||||||
if (sb.length() > 0) {
|
|
||||||
sb.deleteCharAt(sb.length() - 1);
|
|
||||||
}
|
|
||||||
return sb.toString();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
} catch (Exception e) {
|
|
||||||
Log.d(TAG, "WiFi MAC obtaining from network interfaces failed: ", e);
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private String wifiMacFromFileSystem() {
|
|
||||||
try {
|
|
||||||
FileReader fileReader = new FileReader("/sys/class/net/wlan0/address");
|
|
||||||
try {
|
|
||||||
BufferedReader bufferedReader = new BufferedReader(fileReader);
|
|
||||||
try {
|
|
||||||
String readLine = bufferedReader.readLine();
|
|
||||||
bufferedReader.close();
|
|
||||||
fileReader.close();
|
|
||||||
return readLine;
|
|
||||||
} catch (Throwable th) {
|
|
||||||
th.addSuppressed(th);
|
|
||||||
}
|
|
||||||
} catch (Throwable th2) {
|
|
||||||
throw th2;
|
|
||||||
}
|
|
||||||
} catch (Exception e) {
|
|
||||||
Log.d(TAG, "WiFi MAC obtaining from file system failed: ", e);
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
private String bluetoothMac(Context context) {
|
|
||||||
String bluetoothMacFromAdapter = bluetoothMacFromAdapter();
|
|
||||||
if (isInvalidMac(bluetoothMacFromAdapter)) {
|
|
||||||
bluetoothMacFromAdapter = bluetoothMacFromContentResolver(context);
|
|
||||||
}
|
|
||||||
if (isInvalidMac(bluetoothMacFromAdapter)) {
|
|
||||||
bluetoothMacFromAdapter = null;
|
|
||||||
}
|
|
||||||
if (bluetoothMacFromAdapter != null) {
|
|
||||||
return bluetoothMacFromAdapter.toLowerCase();
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
private String bluetoothMacFromAdapter() {
|
|
||||||
try {
|
|
||||||
BluetoothAdapter defaultAdapter = BluetoothAdapter.getDefaultAdapter();
|
|
||||||
if (defaultAdapter == null) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
if (Build.VERSION.SDK_INT < 23) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
Field declaredField = defaultAdapter.getClass().getDeclaredField("mService");
|
|
||||||
declaredField.setAccessible(true);
|
|
||||||
Object obj = declaredField.get(defaultAdapter);
|
|
||||||
if (obj != null) {
|
|
||||||
return (String) obj.getClass().getMethod("getAddress").invoke(obj, new Object[0]);
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
} catch (Exception e) {
|
|
||||||
Log.d(TAG, "BT MAC obtaining from adapter failed: ", e);
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private String bluetoothMacFromContentResolver(Context context) {
|
|
||||||
try {
|
|
||||||
return Settings.Secure.getString(context.getContentResolver(), "bluetooth_address");
|
|
||||||
} catch (Exception e) {
|
|
||||||
Log.d(TAG, "BT MAC obtaining from content resolver failed: ", e);
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean isInvalidSerial(String str) {
|
|
||||||
return TextUtils.isEmpty(str) || EnvironmentCompat.MEDIA_UNKNOWN.equalsIgnoreCase(str);
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean isInvalidMac(String str) {
|
|
||||||
return TextUtils.isEmpty(str) || "02:00:00:00:00:00".equalsIgnoreCase(str) || "00:00:00:00:00:00".equalsIgnoreCase(str);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -57,7 +57,7 @@ public class DNRInjector {
|
|||||||
if (dialog != null) {
|
if (dialog != null) {
|
||||||
try {
|
try {
|
||||||
peerId = dialog.getId();
|
peerId = dialog.getId();
|
||||||
} catch (Exception e){
|
} catch (Exception e) {
|
||||||
Log.d("DialoggetId", "null");
|
Log.d("DialoggetId", "null");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -139,7 +139,7 @@ public class DNRInjector {
|
|||||||
if (dialog != null) {
|
if (dialog != null) {
|
||||||
try {
|
try {
|
||||||
peerId = dialog.getId();
|
peerId = dialog.getId();
|
||||||
} catch (Exception e){
|
} catch (Exception e) {
|
||||||
Log.d("DialoggetId", "null");
|
Log.d("DialoggetId", "null");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -178,7 +178,7 @@ public class DNRInjector {
|
|||||||
if (dialog != null) {
|
if (dialog != null) {
|
||||||
try {
|
try {
|
||||||
peerId = dialog.getId();
|
peerId = dialog.getId();
|
||||||
} catch (Exception e){
|
} catch (Exception e) {
|
||||||
Log.d("DialoggetId", "null");
|
Log.d("DialoggetId", "null");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -240,7 +240,7 @@ public class DNRInjector {
|
|||||||
if (dialog != null) {
|
if (dialog != null) {
|
||||||
try {
|
try {
|
||||||
peerId = dialog.getId();
|
peerId = dialog.getId();
|
||||||
} catch (Exception e){
|
} catch (Exception e) {
|
||||||
Log.d("DialoggetId", "null");
|
Log.d("DialoggetId", "null");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -312,7 +312,7 @@ public class DNRInjector {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (msg instanceof MsgFromUser){
|
if (msg instanceof MsgFromUser) {
|
||||||
var text = ((MsgFromUser) msg).f();
|
var text = ((MsgFromUser) msg).f();
|
||||||
var fullMsg = ((MsgFromUser) msg).j2(); // text + reply
|
var fullMsg = ((MsgFromUser) msg).j2(); // text + reply
|
||||||
var reply = fullMsg.substring(text.length() + 1);
|
var reply = fullMsg.substring(text.length() + 1);
|
||||||
|
|||||||
@@ -1,121 +1,133 @@
|
|||||||
package ru.vtosters.lite.downloaders;
|
package ru.vtosters.lite.downloaders;
|
||||||
|
|
||||||
import android.os.Environment;
|
import static ru.vtosters.lite.utils.AccountManagerUtils.getUserId;
|
||||||
import android.util.Log;
|
import static ru.vtosters.lite.utils.AndroidUtils.getString;
|
||||||
|
|
||||||
import androidx.core.app.NotificationCompat;
|
import android.os.Environment;
|
||||||
import androidx.core.app.NotificationManagerCompat;
|
|
||||||
|
|
||||||
import com.vk.core.util.ToastUtils;
|
import com.vk.core.util.ToastUtils;
|
||||||
import com.vk.dto.music.MusicTrack;
|
import com.vk.dto.music.MusicTrack;
|
||||||
|
import com.vk.dto.music.Playlist;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
|
||||||
import ru.vtosters.lite.downloaders.notifications.NotificationChannels;
|
import bruhcollective.itaysonlab.libvkx.client.LibVKXClient;
|
||||||
import ru.vtosters.lite.music.Callback;
|
import ru.vtosters.lite.music.cache.CacheDatabaseDelegate;
|
||||||
import ru.vtosters.lite.music.FFMpeg;
|
import ru.vtosters.lite.music.cache.FileCacheImplementation;
|
||||||
import ru.vtosters.lite.music.M3UDownloader;
|
import ru.vtosters.lite.music.callback.MusicCallbackBuilder;
|
||||||
import ru.vtosters.lite.music.MP3Downloader;
|
import ru.vtosters.lite.music.converter.playlist.PlaylistConverter;
|
||||||
import ru.vtosters.lite.utils.AndroidUtils;
|
import ru.vtosters.lite.music.downloader.AudioGet;
|
||||||
|
import ru.vtosters.lite.music.downloader.PlaylistDownloader;
|
||||||
|
import ru.vtosters.lite.music.downloader.TrackDownloader;
|
||||||
|
import ru.vtosters.lite.music.notification.MusicNotificationBuilder;
|
||||||
|
import ru.vtosters.lite.utils.IOUtils;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Entrypoint for downloading audio
|
||||||
|
* <p>
|
||||||
|
* The actual code is in {@link ru.vtosters.lite.music}
|
||||||
|
*/
|
||||||
|
|
||||||
public class AudioDownloader {
|
public class AudioDownloader {
|
||||||
private static NotificationManagerCompat notificationManager = NotificationManagerCompat.from(AndroidUtils.getGlobalContext());
|
|
||||||
|
|
||||||
public static void downloadAudio(MusicTrack track) {
|
public static void downloadPlaylist(Playlist playlist) {
|
||||||
if (AndroidUtils.getDefaultPrefs().getBoolean("new_music_downloading_way", false)) {
|
var tracks = PlaylistConverter.getPlaylist(playlist);
|
||||||
downloadMP3(track);
|
|
||||||
} else {
|
var playlistName = IOUtils.getValidFileName(playlist.g);
|
||||||
downloadM3U8(track);
|
|
||||||
}
|
var musicPath = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_MUSIC).getAbsolutePath();
|
||||||
|
var downloadPath = musicPath + File.separator + playlistName;
|
||||||
|
|
||||||
|
var notificationId = playlistName.hashCode();
|
||||||
|
var notification = MusicNotificationBuilder.buildPlaylistDownloadNotification(playlistName, notificationId);
|
||||||
|
|
||||||
|
PlaylistDownloader.downloadPlaylist(
|
||||||
|
tracks,
|
||||||
|
IOUtils.getValidFileName(playlist.g),
|
||||||
|
downloadPath,
|
||||||
|
MusicCallbackBuilder.buildPlaylistCallback(tracks.size(), notification, notificationId)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void downloadM3U8(MusicTrack track) {
|
|
||||||
|
public static void downloadAudio(MusicTrack track) {
|
||||||
|
downloadM3U8(track, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void cacheTrack(MusicTrack track) {
|
||||||
|
var trackId = track.y1();
|
||||||
|
|
||||||
|
if (CacheDatabaseDelegate.isCached(trackId)) {
|
||||||
|
CacheDatabaseDelegate.removeTrackFromCache(LibVKXClient.asId(track));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var trackFile = FileCacheImplementation.getTrackFile(trackId);
|
||||||
|
if (!trackFile.exists())
|
||||||
|
trackFile.getParentFile().mkdirs();
|
||||||
|
downloadM3U8(track, true);
|
||||||
|
MusicNotificationBuilder.notifySavingToCache(track);
|
||||||
|
CacheDatabaseDelegate.insertTrack(track);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void cachePlaylist(Playlist playlist) {
|
||||||
|
var tracks = PlaylistConverter.getPlaylist(playlist);
|
||||||
|
|
||||||
|
var notificationId = playlist.g.hashCode();
|
||||||
|
var notification = MusicNotificationBuilder.buildPlaylistDownloadNotification(playlist.g, notificationId);
|
||||||
|
|
||||||
|
PlaylistDownloader.cachePlaylist(
|
||||||
|
tracks,
|
||||||
|
MusicCallbackBuilder.buildPlaylistCallback(tracks.size(), notification, notificationId)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void cacheAllAudios() {
|
||||||
|
var tracks = AudioGet.getAudios();
|
||||||
|
|
||||||
|
var notificationId = getUserId();
|
||||||
|
var notification = MusicNotificationBuilder.buildAllAudiosDownloadNotification(notificationId);
|
||||||
|
|
||||||
|
PlaylistDownloader.cachePlaylist(
|
||||||
|
tracks,
|
||||||
|
MusicCallbackBuilder.buildPlaylistCallback(tracks.size(), notification, notificationId)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void downloadAllAudios() {
|
||||||
|
var tracks = AudioGet.getAudios();
|
||||||
|
|
||||||
|
var notificationId = getUserId();
|
||||||
|
var notification = MusicNotificationBuilder.buildAllAudiosDownloadNotification(notificationId);
|
||||||
|
|
||||||
|
var playlistName = "Audios of " + getUserId();
|
||||||
|
|
||||||
|
var musicPath = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_MUSIC).getAbsolutePath();
|
||||||
|
var downloadPath = musicPath + File.separator + playlistName;
|
||||||
|
|
||||||
|
PlaylistDownloader.downloadPlaylist(
|
||||||
|
tracks,
|
||||||
|
playlistName,
|
||||||
|
downloadPath,
|
||||||
|
MusicCallbackBuilder.buildPlaylistCallback(tracks.size(), notification, notificationId)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void downloadM3U8(MusicTrack track, boolean cache) {
|
||||||
if (track.D == null) {
|
if (track.D == null) {
|
||||||
ToastUtils.a(AndroidUtils.getString("link_audio_error"));
|
ToastUtils.a(getString("link_audio_error"));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var musicPath = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_MUSIC).getAbsolutePath();
|
var musicPath = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_MUSIC).getAbsolutePath();
|
||||||
var musicDir = new File(musicPath);
|
|
||||||
if (!musicDir.exists()) {
|
|
||||||
if (musicDir.mkdirs()) {
|
|
||||||
Log.d("AudioDownloader", "Created music dir");
|
|
||||||
} else {
|
|
||||||
Log.e("AudioDownloader", "Failed to create music dir");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var tempId = track.d;
|
var tempId = track.d;
|
||||||
var downloadPath = musicPath + File.separator + tempId;
|
var downloadPath = musicPath + File.separator;
|
||||||
|
var notification = MusicNotificationBuilder.buildDownloadNotification(track, tempId);
|
||||||
|
|
||||||
var notification = buildDownloadNotification(track, tempId);
|
if (cache) {
|
||||||
downloadM3U8(track, downloadPath, new Callback() {
|
TrackDownloader.cacheTrack(track, MusicCallbackBuilder.buildOneTrackCallback(tempId, notification));
|
||||||
@Override
|
} else {
|
||||||
public void onProgress(int progress) {
|
TrackDownloader.downloadTrack(track, downloadPath, MusicCallbackBuilder.buildOneTrackCallback(tempId, notification));
|
||||||
notification.setProgress(100, progress, false);
|
}
|
||||||
notificationManager.notify(tempId, notification.build());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onSuccess() {
|
|
||||||
try {
|
|
||||||
var fileName = track.toString();
|
|
||||||
var success = FFMpeg.convert(downloadPath, musicPath + File.separator + fileName + ".mp3");
|
|
||||||
if (success) {
|
|
||||||
notification
|
|
||||||
.setContentText(AndroidUtils.getString("player_download_finished"))
|
|
||||||
.setProgress(0, 0, false)
|
|
||||||
.setSmallIcon(android.R.drawable.stat_sys_download_done);
|
|
||||||
notificationManager.notify(tempId, notification.build());
|
|
||||||
} else {
|
|
||||||
onFailure();
|
|
||||||
}
|
|
||||||
} catch (UnsatisfiedLinkError e) {
|
|
||||||
Log.e("AudioDownloader", "native libs");
|
|
||||||
Log.e("AudioDownloader", e.getMessage());
|
|
||||||
onFailure();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onFailure() {
|
|
||||||
notification.setContentText(AndroidUtils.getString("load_audio_error")).setProgress(0, 0, false);
|
|
||||||
notificationManager.notify(tempId, notification.build());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onSizeReceived(long size, long header) {
|
|
||||||
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void downloadM3U8(MusicTrack track, String path, Callback callback) {
|
|
||||||
File outDir = new File(path);
|
|
||||||
if (!outDir.exists())
|
|
||||||
if (outDir.mkdir())
|
|
||||||
Log.v("AudioDownloader", "Directory created");
|
|
||||||
else
|
|
||||||
Log.e("AudioDownloader", "Directory creation failed");
|
|
||||||
Log.i("AudioDownloader", "Downloading audio to " + path);
|
|
||||||
M3UDownloader.execute(track.D, outDir, callback);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void downloadMP3(MusicTrack track) {
|
|
||||||
MP3Downloader.execute(track);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static NotificationCompat.Builder buildDownloadNotification(MusicTrack track, int id) {
|
|
||||||
var notificationBuilder = new NotificationCompat.Builder(AndroidUtils.getGlobalContext(), NotificationChannels.MUSIC_DOWNLOAD_CHANNEL_ID)
|
|
||||||
.setSmallIcon(android.R.drawable.stat_sys_download)
|
|
||||||
.setContentTitle(AndroidUtils.getString("audio_downloading"))
|
|
||||||
.setContentText(track.toString())
|
|
||||||
.setPriority(NotificationCompat.PRIORITY_LOW)
|
|
||||||
.setCategory(NotificationCompat.CATEGORY_PROGRESS)
|
|
||||||
.setAutoCancel(true);
|
|
||||||
notificationBuilder.setProgress(100, 0, false);
|
|
||||||
notificationManager.notify(id, notificationBuilder.build());
|
|
||||||
return notificationBuilder;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,11 +1,14 @@
|
|||||||
package ru.vtosters.lite.downloaders;
|
package ru.vtosters.lite.downloaders;
|
||||||
|
|
||||||
import static ru.vtosters.lite.encryption.EncryptProvider.decryptMessage;
|
import static ru.vtosters.lite.encryption.EncryptProvider.decryptMessage;
|
||||||
import static ru.vtosters.lite.net.Request.makeRequest;
|
import static ru.vtosters.lite.net.Request.makeRequest;
|
||||||
import static ru.vtosters.lite.proxy.ProxyUtils.getApi;
|
import static ru.vtosters.lite.proxy.ProxyUtils.getApi;
|
||||||
import static ru.vtosters.lite.utils.AccountManagerUtils.getUserId;
|
import static ru.vtosters.lite.utils.AccountManagerUtils.getUserId;
|
||||||
import static ru.vtosters.lite.utils.AccountManagerUtils.getUserToken;
|
import static ru.vtosters.lite.utils.AccountManagerUtils.getUserToken;
|
||||||
|
import static ru.vtosters.lite.utils.AndroidUtils.getArray;
|
||||||
import static ru.vtosters.lite.utils.AndroidUtils.getGlobalContext;
|
import static ru.vtosters.lite.utils.AndroidUtils.getGlobalContext;
|
||||||
import static ru.vtosters.lite.utils.AndroidUtils.getResources;
|
import static ru.vtosters.lite.utils.AndroidUtils.getResources;
|
||||||
|
import static ru.vtosters.lite.utils.AndroidUtils.getString;
|
||||||
|
|
||||||
import android.util.SparseArray;
|
import android.util.SparseArray;
|
||||||
import android.widget.Toast;
|
import android.widget.Toast;
|
||||||
@@ -28,18 +31,16 @@ import java.util.List;
|
|||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
public class MessagesDownloader{
|
public class MessagesDownloader {
|
||||||
|
private static final String VK_DOMAIN = "vk.com";
|
||||||
private static SimpleDateFormat sdformat;
|
private static SimpleDateFormat sdformat;
|
||||||
|
|
||||||
private static SparseArray<MiniUser> usersArray;
|
private static SparseArray<MiniUser> usersArray;
|
||||||
|
|
||||||
private static final String VK_DOMAIN = "vk.com";
|
public static String formatTime(long now) {
|
||||||
|
|
||||||
public static String formatTime(long now){
|
|
||||||
return sdformat.format(new Date(now));
|
return sdformat.format(new Date(now));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String join(CharSequence delimiter, Iterable<? extends CharSequence> elements){
|
public static String join(CharSequence delimiter, Iterable<? extends CharSequence> elements) {
|
||||||
Objects.requireNonNull(delimiter);
|
Objects.requireNonNull(delimiter);
|
||||||
Objects.requireNonNull(elements);
|
Objects.requireNonNull(elements);
|
||||||
|
|
||||||
@@ -52,7 +53,48 @@ public class MessagesDownloader{
|
|||||||
return builder.toString();
|
return builder.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void downloadDialog(int peer_id, DialogDownloaderFormatProvider format, File out) throws Exception{
|
private static String getPollHtml(JSONObject poll) throws JSONException {
|
||||||
|
StringBuilder pollHtml = new StringBuilder(
|
||||||
|
"<div class=\"vtex-milk-msg poll\">" +
|
||||||
|
"<p style=\"text-align:center;\">" + poll.optString("question") + "</p>"
|
||||||
|
);
|
||||||
|
|
||||||
|
var answers = poll.optJSONArray("answers");
|
||||||
|
|
||||||
|
for (int i = 0; i < answers.length(); i++) {
|
||||||
|
var jsonObject = answers.optJSONObject(i);
|
||||||
|
if (jsonObject != null)
|
||||||
|
pollHtml.append("<hr><p>").append(jsonObject.optString("text")).append(" · ").append(jsonObject.optString("votes")).append(" (").append(jsonObject.optString("rate")).append("%)</p>");
|
||||||
|
}
|
||||||
|
|
||||||
|
pollHtml.append("<hr><p style=\"text-align:center;\">").append(getString("chat_export_poll_voted")).append(" ").append(poll.optString("votes")).append(" ").append(getString("chat_export_users_name")).append("</p>");
|
||||||
|
|
||||||
|
return pollHtml.append("</div>").toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String getVideoHtml(JSONObject files) throws JSONException {
|
||||||
|
if (files == null) return getString("chat_export_video_nolinks");
|
||||||
|
|
||||||
|
Iterator<?> keys = files.keys();
|
||||||
|
StringBuilder videoHtml = new StringBuilder();
|
||||||
|
|
||||||
|
int qualityIndex = 0;
|
||||||
|
String[] quality = {"144", "240", "360", "480", "720", "1080", "1440", "2160"};
|
||||||
|
|
||||||
|
while (keys.hasNext()) {
|
||||||
|
String key = (String) keys.next();
|
||||||
|
if (key.equals("mp4_" + quality[qualityIndex])) {
|
||||||
|
videoHtml.append("<a class=\"msg-attach-link\" href=\"").append(files.get(key)).append("\">").append(quality[qualityIndex]).append("p</a>").append(" ");
|
||||||
|
|
||||||
|
if (qualityIndex == quality.length - 1) break;
|
||||||
|
++qualityIndex;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return videoHtml.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void downloadDialog(int peer_id, DialogDownloaderFormatProvider format, File out) throws Exception {
|
||||||
sdformat = new SimpleDateFormat("EEE, d MMM yyyy HH:mm:ss", getResources().getConfiguration().locale);
|
sdformat = new SimpleDateFormat("EEE, d MMM yyyy HH:mm:ss", getResources().getConfiguration().locale);
|
||||||
|
|
||||||
FileOutputStream fos = new FileOutputStream(out);
|
FileOutputStream fos = new FileOutputStream(out);
|
||||||
@@ -68,14 +110,14 @@ public class MessagesDownloader{
|
|||||||
}
|
}
|
||||||
fos.write(format.provideDocumentEnd().getBytes(StandardCharsets.UTF_8));
|
fos.write(format.provideDocumentEnd().getBytes(StandardCharsets.UTF_8));
|
||||||
fos.close();
|
fos.close();
|
||||||
Toast.makeText(getGlobalContext(), "Сохранено как " + out.getAbsolutePath(), Toast.LENGTH_SHORT).show();
|
Toast.makeText(getGlobalContext(), getString("saved_as") + " " + out.getAbsolutePath(), Toast.LENGTH_SHORT).show();
|
||||||
} catch (IOException | JSONException e) {
|
} catch (IOException | JSONException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void fetchDialogInfo(int peer_id, int offset, FetchListener fl){
|
public void fetchDialogInfo(int peer_id, int offset, FetchListener fl) {
|
||||||
makeRequest("https://" + getApi() + "/method/messages.getHistory?extended=1&v=5.140&offset=" + offset + "&count=200&peer_id=" + peer_id + "&access_token=" + getUserToken(),
|
makeRequest("https://" + getApi() + "/method/messages.getHistory?extended=1&v=5.140&offset=" + offset + "&count=200&peer_id=" + peer_id + "&access_token=" + getUserToken(),
|
||||||
response -> {
|
response -> {
|
||||||
try {
|
try {
|
||||||
@@ -97,7 +139,7 @@ public class MessagesDownloader{
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<MiniMsg> parseMessages(JSONArray jsonArray) throws JSONException{
|
private List<MiniMsg> parseMessages(JSONArray jsonArray) throws JSONException {
|
||||||
ArrayList<MiniMsg> thing = new ArrayList<>();
|
ArrayList<MiniMsg> thing = new ArrayList<>();
|
||||||
|
|
||||||
for (int i = 0; i < jsonArray.length(); i++) {
|
for (int i = 0; i < jsonArray.length(); i++) {
|
||||||
@@ -108,7 +150,7 @@ public class MessagesDownloader{
|
|||||||
return thing;
|
return thing;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void parseUsers(SparseArray<MiniUser> array, @Nullable JSONArray jsonArray, boolean groups) throws JSONException{
|
private void parseUsers(SparseArray<MiniUser> array, @Nullable JSONArray jsonArray, boolean groups) throws JSONException {
|
||||||
if (jsonArray == null) return;
|
if (jsonArray == null) return;
|
||||||
|
|
||||||
for (int i = 0; i < jsonArray.length(); i++) {
|
for (int i = 0; i < jsonArray.length(); i++) {
|
||||||
@@ -117,11 +159,11 @@ public class MessagesDownloader{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
interface FetchListener{
|
interface FetchListener {
|
||||||
void onReceive(SparseArray<MiniUser> users, List<MiniMsg> messages);
|
void onReceive(SparseArray<MiniUser> users, List<MiniMsg> messages);
|
||||||
}
|
}
|
||||||
|
|
||||||
static class MiniUser{
|
static class MiniUser {
|
||||||
public String firstName;
|
public String firstName;
|
||||||
public String lastName;
|
public String lastName;
|
||||||
public boolean isGroup;
|
public boolean isGroup;
|
||||||
@@ -137,7 +179,7 @@ public class MessagesDownloader{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static class MiniMsg{
|
static class MiniMsg {
|
||||||
long date;
|
long date;
|
||||||
int fromId;
|
int fromId;
|
||||||
int id; // message id
|
int id; // message id
|
||||||
@@ -148,7 +190,7 @@ public class MessagesDownloader{
|
|||||||
JSONObject chat_action;
|
JSONObject chat_action;
|
||||||
JSONObject geo;
|
JSONObject geo;
|
||||||
|
|
||||||
public MiniMsg(JSONObject obj) throws JSONException{
|
public MiniMsg(JSONObject obj) throws JSONException {
|
||||||
date = obj.getLong("date") * 1000;
|
date = obj.getLong("date") * 1000;
|
||||||
fromId = obj.getInt("from_id");
|
fromId = obj.getInt("from_id");
|
||||||
id = obj.getInt("id");
|
id = obj.getInt("id");
|
||||||
@@ -171,7 +213,7 @@ public class MessagesDownloader{
|
|||||||
}
|
}
|
||||||
|
|
||||||
// This class defines everything which is needed to create an output file
|
// This class defines everything which is needed to create an output file
|
||||||
abstract static class DialogDownloaderFormatProvider{
|
abstract static class DialogDownloaderFormatProvider {
|
||||||
// Internal, for JSON/HTML
|
// Internal, for JSON/HTML
|
||||||
abstract String provideDocumentStart(String dialogName, String date);
|
abstract String provideDocumentStart(String dialogName, String date);
|
||||||
|
|
||||||
@@ -182,9 +224,9 @@ public class MessagesDownloader{
|
|||||||
abstract String provideMessage(MiniMsg message, MiniUser user) throws JSONException;
|
abstract String provideMessage(MiniMsg message, MiniUser user) throws JSONException;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class HtmlDialogDownloaderFormatProvider extends DialogDownloaderFormatProvider{
|
public static class HtmlDialogDownloaderFormatProvider extends DialogDownloaderFormatProvider {
|
||||||
@Override
|
@Override
|
||||||
String provideDocumentStart(String dialogName, String date){
|
String provideDocumentStart(String dialogName, String date) {
|
||||||
String style = ".vtex-milk-msg {\n" +
|
String style = ".vtex-milk-msg {\n" +
|
||||||
" border-radius: 8px;\n" +
|
" border-radius: 8px;\n" +
|
||||||
" padding: 24px;\n" +
|
" padding: 24px;\n" +
|
||||||
@@ -276,21 +318,21 @@ public class MessagesDownloader{
|
|||||||
"\n" +
|
"\n" +
|
||||||
"";
|
"";
|
||||||
|
|
||||||
return "<html><head><meta name=\"viewport\" content=\"width=device-width, initial-scale=1\"><meta charset=\"utf-8\"><title>Экспорт из VTLite</title><style>" + style + "</style></head><body>";
|
return "<html><head><meta name=\"viewport\" content=\"width=device-width, initial-scale=1\"><meta charset=\"utf-8\"><title>" + getString("chat_export_title") + "</title><style>" + style + "</style></head><body>";
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
String provideDocumentEnd(){
|
String provideDocumentEnd() {
|
||||||
return "</div></body></html>";
|
return "</div></body></html>";
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
String provideHeader(String dialogName, String date){
|
String provideHeader(String dialogName, String date) {
|
||||||
return "<div class=\"vtex-milk-header\"><h4 class=\"vtex-milk-header-txt\">VTLite</h4><h5 class=\"vtex-milk-header-sub\">Экспорт истории чата (" + date + ")</h5></div><div class=\"vtex-milk-msgcont\">";
|
return "<div class=\"vtex-milk-header\"><h4 class=\"vtex-milk-header-txt\">VTLite</h4><h5 class=\"vtex-milk-header-sub\">" + getString("chat_export_header") + " (" + date + ")</h5></div><div class=\"vtex-milk-msgcont\">";
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
String provideMessage(MiniMsg message, MiniUser user) throws JSONException{
|
String provideMessage(MiniMsg message, MiniUser user) throws JSONException {
|
||||||
String isOut = (user.id == getUserId()) ? " vtex-milk-msg-out" : "";
|
String isOut = (user.id == getUserId()) ? " vtex-milk-msg-out" : "";
|
||||||
|
|
||||||
String geoPosition = "";
|
String geoPosition = "";
|
||||||
@@ -307,19 +349,19 @@ public class MessagesDownloader{
|
|||||||
}
|
}
|
||||||
|
|
||||||
String chatAction = (message.chat_action != null) ? getHtmlForChatAction(message.chat_action) : "";
|
String chatAction = (message.chat_action != null) ? getHtmlForChatAction(message.chat_action) : "";
|
||||||
String attaches = (message.attachments.size() > 0) ? "<p class=\"msg-attaches\">Вложения: " + getHtmlForAttach(message.attachments) + "</p>" : "";
|
String attaches = (message.attachments.size() > 0) ? "<p class=\"msg-attaches\">" + getString("attachments") + ": " + getHtmlForAttach(message.attachments) + "</p>" : "";
|
||||||
String reply = (message.reply_message != null) ? provideReply(message.reply_message) : "";
|
String reply = (message.reply_message != null) ? provideReply(message.reply_message) : "";
|
||||||
String fwdMessages = (message.fwd_messages.size() > 0) ? provideForwardMessages(message.fwd_messages) : "";
|
String fwdMessages = (message.fwd_messages.size() > 0) ? provideForwardMessages(message.fwd_messages) : "";
|
||||||
String userLink = (user.isGroup ? "club" : "id") + user.id;
|
String userLink = (user.isGroup ? "club" : "id") + user.id;
|
||||||
|
|
||||||
return "<div class=\"vtex-milk-msg" + isOut + "\" id=\"" + message.id + "\">" +
|
return "<div class=\"vtex-milk-msg" + isOut + "\" id=\"" + message.id + "\">" +
|
||||||
"<p class=\"msg-from\">от <a href=\"https://" + VK_DOMAIN + "/" + userLink + "\">" + user.firstName + " " + user.lastName + "</a> <span class=\"msg-from-date\">" + formatTime(message.date) + "</span></p>" + // TODO photo100
|
"<p class=\"msg-from\">" + getString("from_lower") + " <a href=\"https://" + VK_DOMAIN + "/" + userLink + "\">" + user.firstName + " " + user.lastName + "</a> <span class=\"msg-from-date\">" + formatTime(message.date) + "</span></p>" + // TODO photo100
|
||||||
"<p class=\"msg-body\">" + mentionsReplace(message.text) + "</p>" +
|
"<p class=\"msg-body\">" + mentionsReplace(message.text) + "</p>" +
|
||||||
geoPosition +
|
geoPosition +
|
||||||
chatAction +
|
chatAction +
|
||||||
attaches +
|
attaches +
|
||||||
reply +
|
reply +
|
||||||
fwdMessages +
|
fwdMessages +
|
||||||
"</div>";
|
"</div>";
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -336,14 +378,14 @@ public class MessagesDownloader{
|
|||||||
if (fwdMessages != null) {
|
if (fwdMessages != null) {
|
||||||
var length = fwdMessages.length();
|
var length = fwdMessages.length();
|
||||||
if (length > 0) text = length + " " + pluralMsg(length);
|
if (length > 0) text = length + " " + pluralMsg(length);
|
||||||
} else text = "Вложение";
|
} else text = getString("attachment"); // Вложение
|
||||||
}
|
}
|
||||||
|
|
||||||
return "<a href=\"#" + messageId + "\" class=\"msg-attach-link\">" +
|
return "<a href=\"#" + messageId + "\" class=\"msg-attach-link\">" +
|
||||||
"<div class=\"msg-reply\">" +
|
"<div class=\"msg-reply\">" +
|
||||||
"<p class=\"reply-header\">Пересланное сообщение</p>" +
|
"<p class=\"reply-header\">" + getString("vkim_msg_fwd_single") + "</p>" +
|
||||||
"<p class=\"reply-content\">" + user.firstName + " " + user.lastName + ": " + text + "</p>" +
|
"<p class=\"reply-content\">" + user.firstName + " " + user.lastName + ": " + text + "</p>" +
|
||||||
"</div>" +
|
"</div>" +
|
||||||
"</a>";
|
"</a>";
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -382,7 +424,7 @@ public class MessagesDownloader{
|
|||||||
|
|
||||||
JSONObject reply_message = fwd_message.optJSONObject("reply_message");
|
JSONObject reply_message = fwd_message.optJSONObject("reply_message");
|
||||||
|
|
||||||
var attachesHtml = (attaches.size() > 0) ? "Вложения: " + getHtmlForAttach(attaches) : "";
|
var attachesHtml = (attaches.size() > 0) ? getString("attachments") + ": " + getHtmlForAttach(attaches) : "";
|
||||||
var replyHtml = (reply_message != null) ? provideReply(reply_message) : "";
|
var replyHtml = (reply_message != null) ? provideReply(reply_message) : "";
|
||||||
var fwdsHtml = (fwdsMsg.size() > 0) ? provideForwardMessages(fwdsMsg) : ""; // recursion XD :>
|
var fwdsHtml = (fwdsMsg.size() > 0) ? provideForwardMessages(fwdsMsg) : ""; // recursion XD :>
|
||||||
|
|
||||||
@@ -405,7 +447,7 @@ public class MessagesDownloader{
|
|||||||
}
|
}
|
||||||
|
|
||||||
private String pluralMsg(int count) {
|
private String pluralMsg(int count) {
|
||||||
String[] plurals = {"сообщение", "сообщения", "сообщений"};
|
String[] plurals = getArray("msg_plurals");
|
||||||
|
|
||||||
var hundredModulo = count % 100;
|
var hundredModulo = count % 100;
|
||||||
var tenModulo = count % 10;
|
var tenModulo = count % 10;
|
||||||
@@ -422,24 +464,24 @@ public class MessagesDownloader{
|
|||||||
|
|
||||||
StringBuilder htmlAction = new StringBuilder("<p class=\"chat-action\">");
|
StringBuilder htmlAction = new StringBuilder("<p class=\"chat-action\">");
|
||||||
|
|
||||||
switch(type) {
|
switch (type) {
|
||||||
case "chat_photo_update":
|
case "chat_photo_update":
|
||||||
htmlAction.append("Обновил фотографию беседы");
|
htmlAction.append(getString("chat_export_avatar_update"));
|
||||||
break;
|
break;
|
||||||
case "chat_photo_remove":
|
case "chat_photo_remove":
|
||||||
htmlAction.append("Удалил фотографию беседы");
|
htmlAction.append(getString("chat_export_avatar_remove"));
|
||||||
break;
|
break;
|
||||||
case "chat_create":
|
case "chat_create":
|
||||||
var name = action.optString("text");
|
var name = action.optString("text");
|
||||||
htmlAction.append("Создал беседу").append((!name.isEmpty()) ? " с названием \"" + name + "\"" : "");
|
htmlAction.append(getString("chat_export_chat_created")).append((!name.isEmpty()) ? " \"" + name + "\"" : "");
|
||||||
break;
|
break;
|
||||||
case "chat_title_update":
|
case "chat_title_update":
|
||||||
var newName = action.optString("text");
|
var newName = action.optString("text");
|
||||||
htmlAction.append("Сменил название беседы").append((!newName.isEmpty()) ? " на \"" + newName : "\"");
|
htmlAction.append(getString("chat_export_name_changed")).append((!newName.isEmpty()) ? (" " + getString("chat_export_to") + " \"" + newName + "\"") : "");
|
||||||
break;
|
break;
|
||||||
case "chat_invite_user":
|
case "chat_invite_user":
|
||||||
var newUserId = action.optInt("member_id");
|
var newUserId = action.optInt("member_id");
|
||||||
htmlAction.append("Добавил ").append((newUserId > 0) ? "пользователя" : "группу");
|
htmlAction.append(getString("chat_export_user_added") + " ").append((newUserId > 0) ? getString("chat_export_type_user") : getString("chat_export_type_group"));
|
||||||
if (newUserId != 0) {
|
if (newUserId != 0) {
|
||||||
var userLink = ((newUserId < 0) ? "club" : "id") + Math.abs(newUserId);
|
var userLink = ((newUserId < 0) ? "club" : "id") + Math.abs(newUserId);
|
||||||
htmlAction.append(" <a href=\"https://" + VK_DOMAIN + "/").append(userLink).append("\" class=\"msg-attach-link\">@").append(userLink).append("</a>");
|
htmlAction.append(" <a href=\"https://" + VK_DOMAIN + "/").append(userLink).append("\" class=\"msg-attach-link\">@").append(userLink).append("</a>");
|
||||||
@@ -447,7 +489,7 @@ public class MessagesDownloader{
|
|||||||
break;
|
break;
|
||||||
case "chat_kick_user":
|
case "chat_kick_user":
|
||||||
var removedUserId = action.optInt("member_id");
|
var removedUserId = action.optInt("member_id");
|
||||||
htmlAction.append("Исключил ").append((removedUserId > 0) ? "пользователя" : "группу");
|
htmlAction.append(getString("chat_export_user_kicked") + " ").append((removedUserId > 0) ? getString("chat_export_type_user") : getString("chat_export_type_group"));
|
||||||
if (removedUserId != 0) {
|
if (removedUserId != 0) {
|
||||||
var userLink = ((removedUserId < 0) ? "club" : "id") + Math.abs(removedUserId);
|
var userLink = ((removedUserId < 0) ? "club" : "id") + Math.abs(removedUserId);
|
||||||
htmlAction.append(" <a href=\"https://" + VK_DOMAIN + "/").append(userLink).append("\" class=\"msg-attach-link\">@").append(userLink).append("</a>");
|
htmlAction.append(" <a href=\"https://" + VK_DOMAIN + "/").append(userLink).append("\" class=\"msg-attach-link\">@").append(userLink).append("</a>");
|
||||||
@@ -455,29 +497,29 @@ public class MessagesDownloader{
|
|||||||
break;
|
break;
|
||||||
case "chat_pin_message":
|
case "chat_pin_message":
|
||||||
var message = action.optString("message");
|
var message = action.optString("message");
|
||||||
htmlAction.append("Закрепил сообщение").append((!message.isEmpty()) ? (" с текстом: \"" + message + "\"") : "");
|
htmlAction.append(getString("chat_export_msg_pinned")).append((!message.isEmpty()) ? (" \"" + message + "\"") : "");
|
||||||
break;
|
break;
|
||||||
case "chat_unpin_message":
|
case "chat_unpin_message":
|
||||||
htmlAction.append("Открепил сообщение");
|
htmlAction.append(getString("chat_export_msg_unpinned"));
|
||||||
break;
|
break;
|
||||||
case "chat_invite_user_by_link":
|
case "chat_invite_user_by_link":
|
||||||
htmlAction.append("Вступил в беседу по ссылке");
|
htmlAction.append(getString("chat_export_join_by_link"));
|
||||||
break;
|
break;
|
||||||
case "chat_screenshot":
|
case "chat_screenshot":
|
||||||
htmlAction.append("Сделал скриншот беседы");
|
htmlAction.append(getString("chat_export_chat_screenshot"));
|
||||||
break;
|
break;
|
||||||
case "custom":
|
case "custom":
|
||||||
htmlAction.append(action.optString("message"));
|
htmlAction.append(action.optString("message"));
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
htmlAction.append("Действие не поддерживается (").append(type).append(")");
|
htmlAction.append(getString("vkim_msg_unsupported") + " (").append(type).append(")");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return htmlAction.append("</p>").toString();
|
return htmlAction.append("</p>").toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
private String getHtmlForAttach(List<JSONObject> attaches) throws JSONException{
|
private String getHtmlForAttach(List<JSONObject> attaches) throws JSONException {
|
||||||
StringBuilder rs = new StringBuilder();
|
StringBuilder rs = new StringBuilder();
|
||||||
|
|
||||||
for (JSONObject attach : attaches) {
|
for (JSONObject attach : attaches) {
|
||||||
@@ -486,43 +528,43 @@ public class MessagesDownloader{
|
|||||||
|
|
||||||
if (item == null) continue;
|
if (item == null) continue;
|
||||||
|
|
||||||
switch(type) { // market_album is not supported
|
switch (type) { // market_album is not supported
|
||||||
case "photo":
|
case "photo":
|
||||||
var sizes = item.getJSONArray("sizes");
|
var sizes = item.getJSONArray("sizes");
|
||||||
rs.append("<a href=\"").append(sizes.getJSONObject(sizes.length() - 1).getString("url")).append("\" class=\"msg-attach-link\">фотография</a>");
|
rs.append("<a href=\"").append(sizes.getJSONObject(sizes.length() - 1).getString("url")).append("\" class=\"msg-attach-link\">").append(getString("chat_export_type_photo")).append("</a>");
|
||||||
break;
|
break;
|
||||||
case "doc":
|
case "doc":
|
||||||
rs.append("<a href=\"").append(item.getString("url")).append("\" class=\"msg-attach-link\">документ</a>");
|
rs.append("<a href=\"").append(item.getString("url")).append("\" class=\"msg-attach-link\">").append(getString("chat_export_type_doc")).append("</a>");
|
||||||
break;
|
break;
|
||||||
case "link":
|
case "link":
|
||||||
rs.append("<a href=\"").append(item.getString("url")).append("\" class=\"msg-attach-link\">ссылка</a>");
|
rs.append("<a href=\"").append(item.getString("url")).append("\" class=\"msg-attach-link\">").append(getString("chat_export_type_link")).append("</a>");
|
||||||
break;
|
break;
|
||||||
case "wall":
|
case "wall":
|
||||||
rs.append("<a href=\"https://" + VK_DOMAIN + "/wall").append(item.optString("to_id", item.optString("owner_id"))).append("_").append(item.getString("id")).append("\" class=\"msg-attach-link\">запись на стене</a>");
|
rs.append("<a href=\"https://" + VK_DOMAIN + "/wall").append(item.optString("to_id", item.optString("owner_id"))).append("_").append(item.getString("id")).append("\" class=\"msg-attach-link\">").append(getString("chat_export_type_wallpost")).append("</a>");
|
||||||
break;
|
break;
|
||||||
case "sticker":
|
case "sticker":
|
||||||
rs.append("<img style=\"width:128px;height:128px;\" src=\"").append(item.getJSONArray("images").getJSONObject(1).getString("url")).append("\"/>");
|
rs.append("<img style=\"width:128px;height:128px;\" src=\"").append(item.getJSONArray("images").getJSONObject(1).getString("url")).append("\"/>");
|
||||||
break;
|
break;
|
||||||
case "audio_message":
|
case "audio_message":
|
||||||
rs.append("<a href=\"").append(item.optString("link_mp3")).append("\" class=\"msg-attach-link\">голосовое сообщение</a>");
|
rs.append("<a href=\"").append(item.optString("link_mp3")).append("\" class=\"msg-attach-link\">").append(getString("chat_export_type_audiomsg")).append("</a>");
|
||||||
break;
|
break;
|
||||||
case "audio":
|
case "audio":
|
||||||
rs.append("аудиозапись (").append(item.optString("artist")).append(" — ").append(item.optString("title")).append(")");
|
rs.append(getString("chat_export_type_audio")).append(" (").append(item.optString("artist")).append(" — ").append(item.optString("title")).append(")");
|
||||||
break;
|
break;
|
||||||
case "video":
|
case "video":
|
||||||
rs.append("видеозапись ( ").append(getVideoHtml(item.optJSONObject("files"))).append(")");
|
rs.append(getString("chat_export_type_video")).append(" (").append(getVideoHtml(item.optJSONObject("files"))).append(")");
|
||||||
break;
|
break;
|
||||||
case "wall_reply":
|
case "wall_reply":
|
||||||
var link = "https://" + VK_DOMAIN + "/wall" + item.optString("owner_id") + "_" + item.optString("post_id") + "?reply=" + item.optString("id");
|
var link = "https://" + VK_DOMAIN + "/wall" + item.optString("owner_id") + "_" + item.optString("post_id") + "?reply=" + item.optString("id");
|
||||||
rs.append("<a class=\"msg-attach-link\" href=\"").append(link).append("\">комментарий на стене</a>");
|
rs.append("<a class=\"msg-attach-link\" href=\"").append(link).append("\">").append(getString("chat_export_type_wallreply")).append("</a>");
|
||||||
break;
|
break;
|
||||||
case "story":
|
case "story":
|
||||||
var story_link = "https://" + VK_DOMAIN + "/story" + item.optString("owner_id") + "_" + item.optString("id");
|
var story_link = "https://" + VK_DOMAIN + "/story" + item.optString("owner_id") + "_" + item.optString("id");
|
||||||
rs.append("<a class=\"msg-attach-link\" href=\"").append(story_link).append("\">история</a>");
|
rs.append("<a class=\"msg-attach-link\" href=\"").append(story_link).append("\">").append(getString("chat_export_type_story")).append("</a>");
|
||||||
break;
|
break;
|
||||||
case "podcast":
|
case "podcast":
|
||||||
var podcast_link = "https://" + VK_DOMAIN + "/podcast" + item.optString("owner_id") + "_" + item.optString("id");
|
var podcast_link = "https://" + VK_DOMAIN + "/podcast" + item.optString("owner_id") + "_" + item.optString("id");
|
||||||
rs.append("<a class=\"msg-attach-link\" href=\"").append(podcast_link).append("\">подкаст</a>");
|
rs.append("<a class=\"msg-attach-link\" href=\"").append(podcast_link).append("\">").append(getString("chat_export_type_podcast")).append("</a>");
|
||||||
break;
|
break;
|
||||||
case "gift":
|
case "gift":
|
||||||
rs.append("<img src=\"").append(item.optString("thumb_96")).append("\"/>");
|
rs.append("<img src=\"").append(item.optString("thumb_96")).append("\"/>");
|
||||||
@@ -532,25 +574,25 @@ public class MessagesDownloader{
|
|||||||
|
|
||||||
if (app != null) {
|
if (app != null) {
|
||||||
var miniapp_link = "https://" + VK_DOMAIN + "/app" + app.optString("id");
|
var miniapp_link = "https://" + VK_DOMAIN + "/app" + app.optString("id");
|
||||||
rs.append("<a class=\"msg-attach-link\" href=\"").append(miniapp_link).append("\">мини-приложение</a>");
|
rs.append("<a class=\"msg-attach-link\" href=\"").append(miniapp_link).append("\">").append(getString("chat_export_type_miniapp")).append("</a>");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
rs.append("ошибка");
|
rs.append(getString("chat_export_error"));
|
||||||
break;
|
break;
|
||||||
case "audio_playlist":
|
case "audio_playlist":
|
||||||
var playlist_link = "https://" + VK_DOMAIN + "/music/album/" + item.optString("owner_id") + "_" + item.optString("id") + "_" + item.optString("access_key");
|
var playlist_link = "https://" + VK_DOMAIN + "/music/album/" + item.optString("owner_id") + "_" + item.optString("id") + "_" + item.optString("access_key");
|
||||||
rs.append("<a class=\"msg-attach-link\" href=\"").append(playlist_link).append("\">плейлист (").append(item.optString("title")).append(")</a>");
|
rs.append("<a class=\"msg-attach-link\" href=\"").append(playlist_link).append("\">").append(getString("chat_export_type_playlist")).append(" (").append(item.optString("title")).append(")</a>");
|
||||||
break;
|
break;
|
||||||
case "poll":
|
case "poll":
|
||||||
rs.append((item.optBoolean("anonymous") ? "анонимный" : "публичный")).append(" опрос ").append(getPollHtml(item));
|
rs.append(getString(item.optBoolean("anonymous") ? "chat_export_poll_anon" : "chat_export_poll_publ")).append(" ").append(getString("chat_export_type_poll")).append(" ").append(getPollHtml(item));
|
||||||
break;
|
break;
|
||||||
case "market":
|
case "market":
|
||||||
var market_item_link = "https://" + VK_DOMAIN + "/market" + item.optString("owner_id") + "_" + item.optString("id");
|
var market_item_link = "https://" + VK_DOMAIN + "/market" + item.optString("owner_id") + "_" + item.optString("id");
|
||||||
rs.append("<a class=\"msg-attach-link\" href=\"").append(market_item_link).append("\">товар</a>");
|
rs.append("<a class=\"msg-attach-link\" href=\"").append(market_item_link).append("\">").append(getString("chat_export_type_market")).append("</a>");
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
rs.append("не поддерживается (").append(type).append(")");
|
rs.append(getString("vkim_msg_unsupported")).append(" (").append(type).append(")");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -560,45 +602,4 @@ public class MessagesDownloader{
|
|||||||
return rs.toString();
|
return rs.toString();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static String getPollHtml(JSONObject poll) throws JSONException {
|
|
||||||
StringBuilder pollHtml = new StringBuilder(
|
|
||||||
"<div class=\"vtex-milk-msg poll\">" +
|
|
||||||
"<p style=\"text-align:center;\">" + poll.optString("question") + "</p>"
|
|
||||||
);
|
|
||||||
|
|
||||||
var answers = poll.optJSONArray("answers");
|
|
||||||
|
|
||||||
for (int i = 0; i < answers.length(); i++) {
|
|
||||||
var jsonObject = answers.optJSONObject(i);
|
|
||||||
if (jsonObject != null)
|
|
||||||
pollHtml.append("<hr><p>").append(jsonObject.optString("text")).append(" · ").append(jsonObject.optString("votes")).append(" (").append(jsonObject.optString("rate")).append("%)</p>");
|
|
||||||
}
|
|
||||||
|
|
||||||
pollHtml.append("<hr><p style=\"text-align:center;\">Проголосовало ").append(poll.optString("votes")).append(" чел.</p>");
|
|
||||||
|
|
||||||
return pollHtml.append("</div>").toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
private static String getVideoHtml(JSONObject files) throws JSONException {
|
|
||||||
if (files == null) return "ссылки отсутствуют";
|
|
||||||
|
|
||||||
Iterator< ? > keys = files.keys();
|
|
||||||
StringBuilder videoHtml = new StringBuilder();
|
|
||||||
|
|
||||||
int qualityIndex = 0;
|
|
||||||
String[] quality = {"144", "240", "360", "480", "720", "1080", "1440", "2160"};
|
|
||||||
|
|
||||||
while (keys.hasNext()) {
|
|
||||||
String key = (String) keys.next();
|
|
||||||
if (key.equals("mp4_" + quality[qualityIndex])) {
|
|
||||||
videoHtml.append("<a class=\"msg-attach-link\" href=\"").append(files.get(key)).append("\">").append(quality[qualityIndex]).append("p</a>").append(" ");
|
|
||||||
|
|
||||||
if (qualityIndex == quality.length - 1) break;
|
|
||||||
++qualityIndex;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return videoHtml.toString();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@@ -72,17 +72,21 @@ public class OTADownloader {
|
|||||||
manager.enqueue(request);
|
manager.enqueue(request);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
VkAlertDialog.Builder alertDialog = new VkAlertDialog.Builder(context);
|
|
||||||
alertDialog.setTitle(AndroidUtils.getString("update_error"));
|
new VkAlertDialog.Builder(context)
|
||||||
alertDialog.setMessage(AndroidUtils.getString("update_error_text"));
|
.setTitle(AndroidUtils.getString("update_error"))
|
||||||
alertDialog.setPositiveButton(AndroidUtils.getString("no"), (dialog, which) -> {
|
.setMessage(AndroidUtils.getString("update_error_text"))
|
||||||
dialog.cancel();
|
.setPositiveButton(AndroidUtils.getString("no"),
|
||||||
});
|
(dialog, which) -> dialog.cancel()
|
||||||
alertDialog.setNeutralButton(AndroidUtils.getString("yes"), (dialog, which) -> {
|
)
|
||||||
context.startActivity(new Intent("android.intent.action.VIEW").setData(Uri.parse("https://github.com/vtosters/lite/releases/latest/download/VTLite.apk")));
|
.setNeutralButton(AndroidUtils.getString("yes"),
|
||||||
});
|
(dialog, which) -> {
|
||||||
var alert = alertDialog.create();
|
var intent = new Intent(Intent.ACTION_VIEW)
|
||||||
alert.show();
|
.setData(Uri.parse("https://github.com/vtosters/lite/releases/latest/download/VTLite.apk"));
|
||||||
|
context.startActivity(intent);
|
||||||
|
}
|
||||||
|
)
|
||||||
|
.show();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -112,26 +112,26 @@ public class VideoDownloader {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var builder = new VkAlertDialog.Builder(context);
|
new VkAlertDialog.Builder(context)
|
||||||
builder.setItems(max, ((dialog, which) -> {
|
.setItems(max, ((dialog, which) -> {
|
||||||
var url = urls.get(which);
|
var url = urls.get(which);
|
||||||
DownloadManager.Request request = new DownloadManager.Request(Uri.parse(url));
|
DownloadManager.Request request = new DownloadManager.Request(Uri.parse(url));
|
||||||
request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED);
|
request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED);
|
||||||
request.setTitle(videoFile.toString());
|
request.setTitle(videoFile.toString());
|
||||||
request.allowScanningByMediaScanner();
|
request.allowScanningByMediaScanner();
|
||||||
request.setDestinationInExternalPublicDir(Environment.DIRECTORY_MOVIES, videoFile + ".mp4");
|
request.setDestinationInExternalPublicDir(Environment.DIRECTORY_MOVIES, videoFile + ".mp4");
|
||||||
((DownloadManager) context.getSystemService(Context.DOWNLOAD_SERVICE)).enqueue(request);
|
((DownloadManager) context.getSystemService(Context.DOWNLOAD_SERVICE)).enqueue(request);
|
||||||
}));
|
}))
|
||||||
builder.show();
|
.show();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void parseVideoLink(String url, Context ctx) {
|
public static void parseVideoLink(String url, Context ctx) {
|
||||||
if (url.contains("vk.com/story") || url.contains("vk.com/story")) {
|
if (url.contains("vk.com/story")) {
|
||||||
ToastUtils.a(AndroidUtils.getString("video_dl_stories_not_supported"));
|
ToastUtils.a(AndroidUtils.getString("video_dl_stories_not_supported"));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!url.contains("vk.com/video") || !url.contains("vk.com/video")) {
|
if (!url.contains("vk.com/video")) {
|
||||||
ToastUtils.a(AndroidUtils.getString("video_dl_wrong_link"));
|
ToastUtils.a(AndroidUtils.getString("video_dl_wrong_link"));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
+29
-2
@@ -1,5 +1,7 @@
|
|||||||
package ru.vtosters.lite.downloaders.notifications;
|
package ru.vtosters.lite.downloaders.notifications;
|
||||||
|
|
||||||
|
import static ru.vtosters.lite.utils.AndroidUtils.getString;
|
||||||
|
|
||||||
import android.app.Notification;
|
import android.app.Notification;
|
||||||
import android.app.NotificationChannel;
|
import android.app.NotificationChannel;
|
||||||
import android.app.NotificationManager;
|
import android.app.NotificationManager;
|
||||||
@@ -12,12 +14,21 @@ import ru.vtosters.lite.utils.AndroidUtils;
|
|||||||
|
|
||||||
public class NotificationChannels {
|
public class NotificationChannels {
|
||||||
public static final String MUSIC_DOWNLOAD_CHANNEL_ID = "music_download_channel";
|
public static final String MUSIC_DOWNLOAD_CHANNEL_ID = "music_download_channel";
|
||||||
public static final String MUSIC_DOWNLOAD_CHANNEL_NAME = AndroidUtils.getString("music_dl_title");
|
public static final String MUSIC_DOWNLOAD_CHANNEL_NAME = getString("music_downloading");
|
||||||
public static final String MUSIC_DOWNLOAD_CHANNEL_DESCRIPTION = AndroidUtils.getString("music_dl_progress");
|
public static final String MUSIC_DOWNLOAD_CHANNEL_DESCRIPTION = getString("music_downloading_progress");
|
||||||
|
|
||||||
|
public static final String MUSIC_PLAYLIST_DOWNLOAD_CHANNEL_ID = "music_playlist_download_channel";
|
||||||
|
public static final String MUSIC_PLAYLIST_DOWNLOAD_CHANNEL_NAME = getString("playlist_downloading");
|
||||||
|
public static final String MUSIC_PLAYLIST_DOWNLOAD_CHANNEL_DESCRIPTION = getString("playlist_downloading_progress");
|
||||||
|
|
||||||
|
public static final String MUSIC_CACHING_NAME = getString("caching_track_or_pic");
|
||||||
|
|
||||||
|
private static NotificationManagerCompat notificationManagerCompat;
|
||||||
|
|
||||||
@RequiresApi(api = Build.VERSION_CODES.O)
|
@RequiresApi(api = Build.VERSION_CODES.O)
|
||||||
public static void createChannels() {
|
public static void createChannels() {
|
||||||
createMusicDownloadChannel();
|
createMusicDownloadChannel();
|
||||||
|
createMusicPlaylistDownloadChannel();
|
||||||
}
|
}
|
||||||
|
|
||||||
@RequiresApi(api = Build.VERSION_CODES.O)
|
@RequiresApi(api = Build.VERSION_CODES.O)
|
||||||
@@ -29,4 +40,20 @@ public class NotificationChannels {
|
|||||||
var notificationManager = NotificationManagerCompat.from(AndroidUtils.getGlobalContext());
|
var notificationManager = NotificationManagerCompat.from(AndroidUtils.getGlobalContext());
|
||||||
notificationManager.createNotificationChannel(musicDownloadChannel);
|
notificationManager.createNotificationChannel(musicDownloadChannel);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@RequiresApi(api = Build.VERSION_CODES.O)
|
||||||
|
public static void createMusicPlaylistDownloadChannel() {
|
||||||
|
var musicDownloadChannel = new NotificationChannel(MUSIC_PLAYLIST_DOWNLOAD_CHANNEL_ID, MUSIC_PLAYLIST_DOWNLOAD_CHANNEL_NAME, NotificationManager.IMPORTANCE_LOW);
|
||||||
|
musicDownloadChannel.setDescription(MUSIC_PLAYLIST_DOWNLOAD_CHANNEL_DESCRIPTION);
|
||||||
|
musicDownloadChannel.setShowBadge(true);
|
||||||
|
musicDownloadChannel.setLockscreenVisibility(Notification.VISIBILITY_PRIVATE);
|
||||||
|
var notificationManager = NotificationManagerCompat.from(AndroidUtils.getGlobalContext());
|
||||||
|
notificationManager.createNotificationChannel(musicDownloadChannel);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static NotificationManagerCompat getNotificationManager() {
|
||||||
|
if (notificationManagerCompat == null)
|
||||||
|
notificationManagerCompat = NotificationManagerCompat.from(AndroidUtils.getGlobalContext());
|
||||||
|
return notificationManagerCompat;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -52,18 +52,20 @@ public class EncryptProvider {
|
|||||||
public static int getPeerId(Msg msg) {
|
public static int getPeerId(Msg msg) {
|
||||||
return msg.v1();
|
return msg.v1();
|
||||||
}
|
}
|
||||||
|
|
||||||
// For message editing
|
// For message editing
|
||||||
public static String decryptMessage(MsgFromUser msg, boolean showEmoji) {
|
public static String decryptMessage(MsgFromUser msg, boolean showEmoji) {
|
||||||
var decryptedMessage = decryptMessage(getBody(msg), getPeerId(msg));
|
var decryptedMessage = decryptMessage(getBody(msg), getPeerId(msg));
|
||||||
if (!showEmoji && !decryptedMessage.equals(injectOwnTextAll(getBody(msg)))) decryptedMessage = decryptedMessage.replaceAll("^\uD83D\uDD12 ", "");
|
if (!showEmoji && !decryptedMessage.equals(injectOwnTextAll(getBody(msg))))
|
||||||
|
decryptedMessage = decryptedMessage.replaceAll("^\uD83D\uDD12 ", "");
|
||||||
return decryptedMessage;
|
return decryptedMessage;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String decryptMessage(String msg, MsgListComponent list) {
|
public static String decryptMessage(String msg, MsgListComponent list) {
|
||||||
var peerid = list.G().getId();
|
var peerid = list.G().getId();
|
||||||
var decryptedMessage = decryptMessage(msg, peerid);
|
var decryptedMessage = decryptMessage(msg, peerid);
|
||||||
if (!decryptedMessage.equals(injectOwnTextAll(msg))) decryptedMessage = decryptedMessage.replaceAll("^\uD83D\uDD12 ", "");
|
if (!decryptedMessage.equals(injectOwnTextAll(msg)))
|
||||||
|
decryptedMessage = decryptedMessage.replaceAll("^\uD83D\uDD12 ", "");
|
||||||
return decryptedMessage;
|
return decryptedMessage;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -91,7 +93,8 @@ public class EncryptProvider {
|
|||||||
// For MentionsFormatter that requires CharSequence
|
// For MentionsFormatter that requires CharSequence
|
||||||
public static CharSequence decryptMessage(String msgBody, int peer, boolean showEmoji) {
|
public static CharSequence decryptMessage(String msgBody, int peer, boolean showEmoji) {
|
||||||
var decryptedMessage = decryptMessage(msgBody, peer);
|
var decryptedMessage = decryptMessage(msgBody, peer);
|
||||||
if (!showEmoji && !decryptedMessage.equals(injectOwnTextAll(msgBody))) decryptedMessage = decryptedMessage.replaceAll("^\uD83D\uDD12 ", "");
|
if (!showEmoji && !decryptedMessage.equals(injectOwnTextAll(msgBody)))
|
||||||
|
decryptedMessage = decryptedMessage.replaceAll("^\uD83D\uDD12 ", "");
|
||||||
return decryptedMessage;
|
return decryptedMessage;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,19 @@
|
|||||||
|
package ru.vtosters.lite.feature.discover;
|
||||||
|
|
||||||
|
import com.vk.dto.discover.DiscoverItem;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
public class DiscoverTemplates {
|
||||||
|
public static ArrayList<String> getTemplates() {
|
||||||
|
var templates = DiscoverItem.Template.values();
|
||||||
|
var arrayList = new ArrayList<String>();
|
||||||
|
|
||||||
|
for (var template : templates) {
|
||||||
|
if (template != DiscoverItem.Template.GRID_MEDIA) {
|
||||||
|
arrayList.add(template.b());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return arrayList;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
package ru.vtosters.lite.feature.music;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
|
||||||
|
import com.vk.music.fragment.MusicFragment;
|
||||||
|
|
||||||
|
public class MusicArtistSelectorHook {
|
||||||
|
public static void navigateToSearch(Context context, String artist) {
|
||||||
|
var fr = new MusicFragment.f();
|
||||||
|
fr.a(artist);
|
||||||
|
|
||||||
|
// navigate
|
||||||
|
fr.a(context);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -13,8 +13,6 @@ import android.app.ProgressDialog;
|
|||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
import androidx.exifinterface.media.ExifInterface;
|
|
||||||
|
|
||||||
import com.vk.core.dialogs.alert.VkAlertDialog;
|
import com.vk.core.dialogs.alert.VkAlertDialog;
|
||||||
import com.vk.core.network.Network;
|
import com.vk.core.network.Network;
|
||||||
|
|
||||||
@@ -72,7 +70,7 @@ public class FoafBase {
|
|||||||
|
|
||||||
public static JSONObject getBypassedOnlineInfo(int id) throws JSONException {
|
public static JSONObject getBypassedOnlineInfo(int id) throws JSONException {
|
||||||
var request = new okhttp3.Request.a()
|
var request = new okhttp3.Request.a()
|
||||||
.b(API_VKNEXT + Integer.toString(id))
|
.b(API_VKNEXT + id)
|
||||||
.a();
|
.a();
|
||||||
|
|
||||||
String response = null;
|
String response = null;
|
||||||
@@ -145,15 +143,22 @@ public class FoafBase {
|
|||||||
matcher2.find();
|
matcher2.find();
|
||||||
String normalHumanDate = getNormalHumanDate(Objects.requireNonNull(matcher.group(1)));
|
String normalHumanDate = getNormalHumanDate(Objects.requireNonNull(matcher.group(1)));
|
||||||
getNormalHumanDate(Objects.requireNonNull(matcher2.group(1)));
|
getNormalHumanDate(Objects.requireNonNull(matcher2.group(1)));
|
||||||
VkAlertDialog.Builder a2 = new VkAlertDialog.Builder(context).setTitle(getIdentifier("addinf", "string"));
|
|
||||||
a2.setMessage(getString("foafid") + " " + i + getString("foafregdate") + " " + normalHumanDate + getString("foafdate") + " " + daysPassedFromFoafDate(normalHumanDate)).setPositiveButton(17039370, null).create().show();
|
new VkAlertDialog.Builder(context)
|
||||||
|
.setTitle(getIdentifier("addinf", "string"))
|
||||||
|
.setMessage(getString("foafid") +
|
||||||
|
" " + i + getString("foafregdate")
|
||||||
|
+ " " + normalHumanDate + getString("foafdate")
|
||||||
|
+ " " + daysPassedFromFoafDate(normalHumanDate))
|
||||||
|
.setPositiveButton(android.R.string.ok, null)
|
||||||
|
.show();
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
makeText(getGlobalContext(), getString("foaferr"), LENGTH_SHORT).show();
|
makeText(getGlobalContext(), getString("foaferr"), LENGTH_SHORT).show();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static long daysPassedFromFoafDate(String str) {
|
private static long daysPassedFromFoafDate(String str) {
|
||||||
try {
|
try {
|
||||||
@SuppressLint("SimpleDateFormat")
|
@SuppressLint("SimpleDateFormat")
|
||||||
Date parse = new SimpleDateFormat("yyyy-MM-dd").parse(str.split(" ")[1]);
|
Date parse = new SimpleDateFormat("yyyy-MM-dd").parse(str.split(" ")[1]);
|
||||||
@@ -165,7 +170,7 @@ public class FoafBase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static String getNormalHumanDate(String str) {
|
private static String getNormalHumanDate(String str) {
|
||||||
String[] split = str.split(ExifInterface.GPS_DIRECTION_TRUE);
|
String[] split = str.split("T");
|
||||||
return split[1].split("\\+")[0] + " " + split[0];
|
return split[1].split("\\+")[0] + " " + split[0];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -335,7 +335,7 @@ public class AdBlockHook {
|
|||||||
id = String.valueOf(list.optInt("source_id"));
|
id = String.valueOf(list.optInt("source_id"));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (id.equals("-189659924")){
|
if (id.equals("-189659924")) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,12 +1,13 @@
|
|||||||
package ru.vtosters.lite.hooks;
|
package ru.vtosters.lite.hooks;
|
||||||
|
|
||||||
import static ru.vtosters.lite.dnr.DNRInjector.forceInvalidateDialogActions;
|
import static ru.vtosters.lite.dnr.DNRInjector.forceInvalidateDialogActions;
|
||||||
import static ru.vtosters.lite.utils.AndroidUtils.dp2px;
|
import static ru.vtosters.lite.utils.AndroidUtils.dp2px;
|
||||||
import static ru.vtosters.lite.utils.AndroidUtils.getString;
|
import static ru.vtosters.lite.utils.AndroidUtils.getString;
|
||||||
import static ru.vtosters.lite.utils.AndroidUtils.sendToast;
|
import static ru.vtosters.lite.utils.AndroidUtils.sendToast;
|
||||||
import static ru.vtosters.lite.utils.LifecycleUtils.getCurrentActivity;
|
import static ru.vtosters.lite.utils.LifecycleUtils.getCurrentActivity;
|
||||||
import static ru.vtosters.lite.utils.ThemesUtils.getAlertStyle;
|
|
||||||
import static ru.vtosters.lite.utils.ThemesUtils.getSTextAttr;
|
import static ru.vtosters.lite.utils.ThemesUtils.getSTextAttr;
|
||||||
|
|
||||||
|
import android.app.Activity;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.res.ColorStateList;
|
import android.content.res.ColorStateList;
|
||||||
import android.text.Editable;
|
import android.text.Editable;
|
||||||
@@ -14,8 +15,6 @@ import android.view.ViewGroup;
|
|||||||
import android.widget.EditText;
|
import android.widget.EditText;
|
||||||
import android.widget.LinearLayout;
|
import android.widget.LinearLayout;
|
||||||
|
|
||||||
import androidx.appcompat.app.AlertDialog;
|
|
||||||
|
|
||||||
import com.vk.core.dialogs.alert.VkAlertDialog;
|
import com.vk.core.dialogs.alert.VkAlertDialog;
|
||||||
import com.vk.im.engine.models.dialogs.Dialog;
|
import com.vk.im.engine.models.dialogs.Dialog;
|
||||||
|
|
||||||
@@ -25,8 +24,8 @@ import java.util.Objects;
|
|||||||
import ru.vtosters.lite.encryption.EncryptProvider;
|
import ru.vtosters.lite.encryption.EncryptProvider;
|
||||||
import ru.vtosters.lite.encryption.base.IMProcessor;
|
import ru.vtosters.lite.encryption.base.IMProcessor;
|
||||||
|
|
||||||
public class CryptImHook{
|
public class CryptImHook {
|
||||||
public static boolean isPrivateProcessor(int peerID){
|
public static boolean isPrivateProcessor(int peerID) {
|
||||||
for (IMProcessor processor : EncryptProvider.processors) {
|
for (IMProcessor processor : EncryptProvider.processors) {
|
||||||
if (processor.isUsedToEncrypt(peerID)) {
|
if (processor.isUsedToEncrypt(peerID)) {
|
||||||
return !processor.isPublic();
|
return !processor.isPublic();
|
||||||
@@ -36,7 +35,7 @@ public class CryptImHook{
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void hook(int peerId, Dialog d){
|
public static void hook(int peerId, Dialog d) {
|
||||||
List<IMProcessor> processors = EncryptProvider.processors;
|
List<IMProcessor> processors = EncryptProvider.processors;
|
||||||
|
|
||||||
IMProcessor enabled = null;
|
IMProcessor enabled = null;
|
||||||
@@ -57,7 +56,14 @@ public class CryptImHook{
|
|||||||
}
|
}
|
||||||
|
|
||||||
IMProcessor finalEnabled = enabled;
|
IMProcessor finalEnabled = enabled;
|
||||||
new VkAlertDialog.Builder(getCurrentActivity())
|
Activity ctx = getCurrentActivity();
|
||||||
|
|
||||||
|
if (ctx == null) {
|
||||||
|
sendToast(getString("app_activities_error"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
new VkAlertDialog.Builder(ctx)
|
||||||
.setTitle(getString("encryption_sett"))
|
.setTitle(getString("encryption_sett"))
|
||||||
.setSingleChoiceItems(titles, enabledPosition, (dialog, which) -> {
|
.setSingleChoiceItems(titles, enabledPosition, (dialog, which) -> {
|
||||||
if (which == 0) {
|
if (which == 0) {
|
||||||
@@ -75,10 +81,11 @@ public class CryptImHook{
|
|||||||
|
|
||||||
dialog.dismiss();
|
dialog.dismiss();
|
||||||
forceInvalidateDialogActions(d);
|
forceInvalidateDialogActions(d);
|
||||||
}).create().show();
|
})
|
||||||
|
.show();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void hookPref(int peerId){
|
public static void hookPref(int peerId) {
|
||||||
IMProcessor enabled = null;
|
IMProcessor enabled = null;
|
||||||
String key = null;
|
String key = null;
|
||||||
|
|
||||||
@@ -103,6 +110,11 @@ public class CryptImHook{
|
|||||||
|
|
||||||
Context ctx = getCurrentActivity();
|
Context ctx = getCurrentActivity();
|
||||||
|
|
||||||
|
if (ctx == null) {
|
||||||
|
sendToast(getString("app_activities_error"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
LinearLayout linearLayout = new LinearLayout(ctx);
|
LinearLayout linearLayout = new LinearLayout(ctx);
|
||||||
|
|
||||||
final EditText editText = new EditText(ctx);
|
final EditText editText = new EditText(ctx);
|
||||||
@@ -117,13 +129,14 @@ public class CryptImHook{
|
|||||||
editText.setText(key == null ? "" : key);
|
editText.setText(key == null ? "" : key);
|
||||||
|
|
||||||
IMProcessor finalEnabled = enabled;
|
IMProcessor finalEnabled = enabled;
|
||||||
new AlertDialog.Builder(ctx, getAlertStyle())
|
new VkAlertDialog.Builder(ctx)
|
||||||
.setTitle(getString("encryption_enter_key"))
|
.setTitle(getString("encryption_enter_key"))
|
||||||
.setMessage(String.format(getString("encryption_current_algorithm_title"), enabled.getUIName()))
|
.setMessage(String.format(getString("encryption_current_algorithm_title"), enabled.getUIName()))
|
||||||
.setView(linearLayout)
|
.setView(linearLayout)
|
||||||
.setPositiveButton(android.R.string.ok, (dialog, which) -> {
|
.setPositiveButton(android.R.string.ok, (dialog, which) -> {
|
||||||
Editable edit = editText.getText();
|
Editable edit = editText.getText();
|
||||||
finalEnabled.setEncryptionKeyFor(peerId, edit == null ? null : edit.toString());
|
finalEnabled.setEncryptionKeyFor(peerId, edit == null ? null : edit.toString());
|
||||||
}).setNegativeButton(android.R.string.cancel, null).create().show();
|
}).setNegativeButton(android.R.string.cancel, null)
|
||||||
|
.show();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,4 +1,5 @@
|
|||||||
package ru.vtosters.lite.hooks;
|
package ru.vtosters.lite.hooks;
|
||||||
|
|
||||||
import static ru.vtosters.lite.utils.AndroidUtils.MD5;
|
import static ru.vtosters.lite.utils.AndroidUtils.MD5;
|
||||||
import static ru.vtosters.lite.utils.AndroidUtils.getGlobalContext;
|
import static ru.vtosters.lite.utils.AndroidUtils.getGlobalContext;
|
||||||
import static ru.vtosters.lite.utils.Preferences.getBoolValue;
|
import static ru.vtosters.lite.utils.Preferences.getBoolValue;
|
||||||
@@ -8,7 +9,7 @@ import android.os.Build;
|
|||||||
import android.provider.Settings;
|
import android.provider.Settings;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
public class DeviceInfoHook{
|
public class DeviceInfoHook {
|
||||||
public static String getDeviceInfo(String input) {
|
public static String getDeviceInfo(String input) {
|
||||||
Log.d("DeviceInfoHook", "getDeviceInfo: " + input);
|
Log.d("DeviceInfoHook", "getDeviceInfo: " + input);
|
||||||
if (getBoolValue("hideDeviceInfo", true)) return "";
|
if (getBoolValue("hideDeviceInfo", true)) return "";
|
||||||
|
|||||||
@@ -82,7 +82,8 @@ public class DockBarInjector {
|
|||||||
} while (acquire.invoke(synchronizedPool) != null);
|
} while (acquire.invoke(synchronizedPool) != null);
|
||||||
}
|
}
|
||||||
|
|
||||||
} catch (NoSuchFieldException | IllegalAccessException | ClassNotFoundException | NoSuchMethodException | InvocationTargetException e) {
|
} catch (NoSuchFieldException | IllegalAccessException | ClassNotFoundException |
|
||||||
|
NoSuchMethodException | InvocationTargetException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -29,7 +29,6 @@ import javax.net.ssl.HttpsURLConnection;
|
|||||||
|
|
||||||
public class GcmHook {
|
public class GcmHook {
|
||||||
private static final String agent = String.format("Android-GCM/1.5 (%s %s)", Build.MODEL, Build.MODEL);
|
private static final String agent = String.format("Android-GCM/1.5 (%s %s)", Build.MODEL, Build.MODEL);
|
||||||
public static ArrayList<String> langs = new ArrayList<>();
|
|
||||||
private static KeyPair pair;
|
private static KeyPair pair;
|
||||||
private static int rid = 0;
|
private static int rid = 0;
|
||||||
|
|
||||||
@@ -38,12 +37,12 @@ public class GcmHook {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static String requestTokenV2(String orig) {
|
public static String requestTokenV2(String orig) {
|
||||||
if (musicFixNew()) return "null";
|
if (musicFixNew()) return "null"; //not public
|
||||||
return orig;
|
return orig;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String requestToken(String orig) {
|
public static String requestToken(String orig) {
|
||||||
if (musicFixNew()) return "{null}";
|
if (musicFixNew()) return "{null}"; //not public
|
||||||
if (orig.equals("")) return requestToken();
|
if (orig.equals("")) return requestToken();
|
||||||
return orig;
|
return orig;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -160,7 +160,8 @@ public class JsonInjectors {
|
|||||||
var isPicture = pic.endsWith(".png") || pic.endsWith(".jpg") || pic.endsWith(".jpeg") || pic.endsWith(".webp");
|
var isPicture = pic.endsWith(".png") || pic.endsWith(".jpg") || pic.endsWith(".jpeg") || pic.endsWith(".webp");
|
||||||
|
|
||||||
if (isVerified(peerid)) text = AndroidUtils.getString("i_bought") + " VTosters Premium";
|
if (isVerified(peerid)) text = AndroidUtils.getString("i_bought") + " VTosters Premium";
|
||||||
if (isPrometheus(peerid)) text = AndroidUtils.getString("i_bought") + " VTosters Premium Gold Prime Pro Plus";
|
if (isPrometheus(peerid))
|
||||||
|
text = AndroidUtils.getString("i_bought") + " VTosters Premium Gold Prime Pro Plus";
|
||||||
if (isDeveloper(peerid)) text = AndroidUtils.getString("i_created_poop");
|
if (isDeveloper(peerid)) text = AndroidUtils.getString("i_created_poop");
|
||||||
|
|
||||||
if (!isVerified(peerid) || text.equals("") || peerid == AccountManagerUtils.getUserId() || peerid == 0) {
|
if (!isVerified(peerid) || text.equals("") || peerid == AccountManagerUtils.getUserId() || peerid == 0) {
|
||||||
@@ -282,7 +283,7 @@ public class JsonInjectors {
|
|||||||
if (profiles == null || profiles.length() == 0) return profiles;
|
if (profiles == null || profiles.length() == 0) return profiles;
|
||||||
StringBuilder sb = new StringBuilder();
|
StringBuilder sb = new StringBuilder();
|
||||||
var curVkId = AccountManagerUtils.getUserId();
|
var curVkId = AccountManagerUtils.getUserId();
|
||||||
for (int i=0; i < profiles.length(); i++) {
|
for (int i = 0; i < profiles.length(); i++) {
|
||||||
JSONObject profile = profiles.getJSONObject(i);
|
JSONObject profile = profiles.getJSONObject(i);
|
||||||
int id = profile.optInt("id", -1);
|
int id = profile.optInt("id", -1);
|
||||||
JSONObject onlinfo = profile.optJSONObject("online_info");
|
JSONObject onlinfo = profile.optJSONObject("online_info");
|
||||||
@@ -300,7 +301,7 @@ public class JsonInjectors {
|
|||||||
}
|
}
|
||||||
|
|
||||||
JSONObject bypassedObj = getBypassedOnlineInfo(ids);
|
JSONObject bypassedObj = getBypassedOnlineInfo(ids);
|
||||||
for (int i=0; i < profiles.length(); i++) {
|
for (int i = 0; i < profiles.length(); i++) {
|
||||||
JSONObject profile = profiles.getJSONObject(i);
|
JSONObject profile = profiles.getJSONObject(i);
|
||||||
int id = profile.optInt("id");
|
int id = profile.optInt("id");
|
||||||
JSONObject bypassed = bypassedObj.optJSONObject(Integer.toString(id));
|
JSONObject bypassed = bypassedObj.optJSONObject(Integer.toString(id));
|
||||||
@@ -447,7 +448,7 @@ public class JsonInjectors {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static JSONObject fetchCatalogId(String section) {
|
public static JSONObject fetchCatalogId(String section) {
|
||||||
if (section == null) return null;
|
if (section.isEmpty()) return null;
|
||||||
|
|
||||||
var request = new Request.a()
|
var request = new Request.a()
|
||||||
.b("https://" + getApi() + "/method/catalog.getAudio"
|
.b("https://" + getApi() + "/method/catalog.getAudio"
|
||||||
|
|||||||
@@ -14,18 +14,18 @@ import android.preference.PreferenceManager;
|
|||||||
import com.vk.core.concurrent.VkExecutors;
|
import com.vk.core.concurrent.VkExecutors;
|
||||||
|
|
||||||
import ru.vtosters.lite.downloaders.notifications.NotificationChannels;
|
import ru.vtosters.lite.downloaders.notifications.NotificationChannels;
|
||||||
import ru.vtosters.lite.hooks.ui.SystemThemeChangerHook;
|
|
||||||
import ru.vtosters.lite.ui.dialogs.DisableBattery;
|
import ru.vtosters.lite.ui.dialogs.DisableBattery;
|
||||||
import ru.vtosters.lite.ui.dialogs.InstallGMS;
|
import ru.vtosters.lite.ui.dialogs.InstallGMS;
|
||||||
import ru.vtosters.lite.ui.dialogs.OTADialog;
|
import ru.vtosters.lite.ui.dialogs.OTADialog;
|
||||||
import ru.vtosters.lite.ui.dialogs.ServerDialog;
|
|
||||||
import ru.vtosters.lite.ui.dialogs.Start;
|
import ru.vtosters.lite.ui.dialogs.Start;
|
||||||
import ru.vtosters.lite.utils.DeletedMessagesHandler;
|
import ru.vtosters.lite.utils.DeletedMessagesHandler;
|
||||||
|
|
||||||
public class MainActivityInjector{
|
/**
|
||||||
public static void inject(Activity activity){
|
* @
|
||||||
|
*/
|
||||||
|
public class MainActivityInjector {
|
||||||
|
public static void inject(Activity activity) {
|
||||||
setNeededTheme(activity);
|
setNeededTheme(activity);
|
||||||
ServerDialog.activity = activity;
|
|
||||||
sendRequest();
|
sendRequest();
|
||||||
if (checkupdates()) OTADialog.checkUpdates(activity);
|
if (checkupdates()) OTADialog.checkUpdates(activity);
|
||||||
VkExecutors.x.f().a(DeletedMessagesHandler::reloadMessagesList); // ioScheduler
|
VkExecutors.x.f().a(DeletedMessagesHandler::reloadMessagesList); // ioScheduler
|
||||||
@@ -36,7 +36,7 @@ public class MainActivityInjector{
|
|||||||
.edit()
|
.edit()
|
||||||
.putBoolean("isdark", isDarkTheme())
|
.putBoolean("isdark", isDarkTheme())
|
||||||
.commit();
|
.commit();
|
||||||
SystemThemeChangerHook.onThemeChanged(activity.getResources().getConfiguration());
|
|
||||||
|
|
||||||
VkExecutors.x.q().a(() -> {
|
VkExecutors.x.q().a(() -> {
|
||||||
getInstance().autoCleaningCache();
|
getInstance().autoCleaningCache();
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import static ru.vtosters.lite.utils.Preferences.autoalltranslate;
|
|||||||
import static ru.vtosters.lite.utils.Preferences.autotranslate;
|
import static ru.vtosters.lite.utils.Preferences.autotranslate;
|
||||||
import static ru.vtosters.lite.utils.Preferences.savemsgsett;
|
import static ru.vtosters.lite.utils.Preferences.savemsgsett;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
|
|
||||||
@@ -16,12 +17,13 @@ import java.util.ArrayList;
|
|||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
import ru.vtosters.lite.translators.BaseTranslator;
|
import ru.vtosters.lite.translators.BaseTranslator;
|
||||||
|
import ru.vtosters.lite.utils.LifecycleUtils;
|
||||||
|
|
||||||
public class MessagesHook {
|
public class MessagesHook {
|
||||||
public static String injectOwnText(String oldText) {
|
public static String injectOwnText(String oldText) {
|
||||||
if (!autotranslate() || TextUtils.isEmpty(oldText))
|
if (!autotranslate() || TextUtils.isEmpty(oldText))
|
||||||
return oldText;
|
return oldText;
|
||||||
var instance = BaseTranslator.getInstance();
|
var instance = BaseTranslator.getInstance();
|
||||||
|
|
||||||
return replaceMentions(oldText, instance);
|
return replaceMentions(oldText, instance);
|
||||||
}
|
}
|
||||||
@@ -44,7 +46,8 @@ public class MessagesHook {
|
|||||||
var mentions = new ArrayList<String>();
|
var mentions = new ArrayList<String>();
|
||||||
while (matcher.find()) {
|
while (matcher.find()) {
|
||||||
mentions.add(matcher.group());
|
mentions.add(matcher.group());
|
||||||
matcher.appendReplacement(textBuff, "vtl_mention" + mentionsCount + ""); ++mentionsCount;
|
matcher.appendReplacement(textBuff, "vtl_mention" + mentionsCount + "");
|
||||||
|
++mentionsCount;
|
||||||
}
|
}
|
||||||
matcher.appendTail(textBuff);
|
matcher.appendTail(textBuff);
|
||||||
|
|
||||||
@@ -59,7 +62,7 @@ public class MessagesHook {
|
|||||||
matcherMentions.appendTail(retTextBuff);
|
matcherMentions.appendTail(retTextBuff);
|
||||||
|
|
||||||
return retTextBuff.toString();
|
return retTextBuff.toString();
|
||||||
} catch(Exception e) {
|
} catch (Exception e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
return instance.getTranslation(oldText);
|
return instance.getTranslation(oldText);
|
||||||
}
|
}
|
||||||
@@ -72,6 +75,14 @@ public class MessagesHook {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static Context fixCTX(Context ctx) {
|
||||||
|
if (ctx == null) {
|
||||||
|
return LifecycleUtils.getCurrentActivity();
|
||||||
|
} else {
|
||||||
|
return ctx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public static void injRequest(MethodCall.a req) {
|
public static void injRequest(MethodCall.a req) {
|
||||||
var time = expireTime();
|
var time = expireTime();
|
||||||
|
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ package ru.vtosters.lite.hooks;
|
|||||||
|
|
||||||
import static java.lang.Long.MAX_VALUE;
|
import static java.lang.Long.MAX_VALUE;
|
||||||
import static ru.vtosters.lite.utils.AndroidUtils.getDefaultPrefs;
|
import static ru.vtosters.lite.utils.AndroidUtils.getDefaultPrefs;
|
||||||
|
import static ru.vtosters.lite.utils.AndroidUtils.getGlobalContext;
|
||||||
import static ru.vtosters.lite.utils.AndroidUtils.getPrefsValue;
|
import static ru.vtosters.lite.utils.AndroidUtils.getPrefsValue;
|
||||||
import static ru.vtosters.lite.utils.Preferences.ads;
|
import static ru.vtosters.lite.utils.Preferences.ads;
|
||||||
import static ru.vtosters.lite.utils.Preferences.adsslider;
|
import static ru.vtosters.lite.utils.Preferences.adsslider;
|
||||||
@@ -10,6 +11,9 @@ import static ru.vtosters.lite.utils.Preferences.friendsrecomm;
|
|||||||
import static ru.vtosters.lite.utils.Preferences.getBoolValue;
|
import static ru.vtosters.lite.utils.Preferences.getBoolValue;
|
||||||
import static ru.vtosters.lite.utils.Preferences.vkme;
|
import static ru.vtosters.lite.utils.Preferences.vkme;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.os.PowerManager;
|
||||||
|
|
||||||
import com.vk.core.preference.Preference;
|
import com.vk.core.preference.Preference;
|
||||||
import com.vtosters.lite.api.ExtendedCommunityProfile;
|
import com.vtosters.lite.api.ExtendedCommunityProfile;
|
||||||
|
|
||||||
@@ -43,13 +47,13 @@ public class NewsfeedHook {
|
|||||||
return list;
|
return list;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String[] feedParams(){
|
public static String[] feedParams() {
|
||||||
HashSet<String> params = new HashSet<>();
|
HashSet<String> params = new HashSet<>();
|
||||||
params.add("post");
|
params.add("post");
|
||||||
params.add("photo");
|
params.add("photo");
|
||||||
params.add("photo_tag");
|
params.add("photo_tag");
|
||||||
|
|
||||||
if (!friendsrecomm() && !getBoolValue("donotgetads", false)) {
|
if (!friendsrecomm()) {
|
||||||
params.add("friends_recomm");
|
params.add("friends_recomm");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -58,7 +62,7 @@ public class NewsfeedHook {
|
|||||||
params.add("promo_button");
|
params.add("promo_button");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!authorsrecomm() && !getBoolValue("donotgetads", false)) {
|
if (!authorsrecomm()) {
|
||||||
params.add("authors_rec");
|
params.add("authors_rec");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -104,22 +108,22 @@ public class NewsfeedHook {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static void adsParams(HashSet<String> hashSet) {
|
public static void adsParams(HashSet<String> hashSet) {
|
||||||
if (ads()) {
|
if (ads())
|
||||||
hashSet.add("ads_disabled");
|
hashSet.add("ads_disabled");
|
||||||
if (getBoolValue("donotgetads", false)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
hashSet.add("ads_app");
|
hashSet.add("ads_app");
|
||||||
hashSet.add("ads_site");
|
hashSet.add("ads_site");
|
||||||
hashSet.add("ads_post");
|
hashSet.add("ads_post");
|
||||||
if (!adsslider()) {
|
if (!adsslider())
|
||||||
hashSet.add("ads_app_slider");
|
hashSet.add("ads_app_slider");
|
||||||
}
|
|
||||||
hashSet.add("ads_site_slider");
|
hashSet.add("ads_site_slider");
|
||||||
hashSet.add("ads_app_video");
|
hashSet.add("ads_app_video");
|
||||||
hashSet.add("ads_post_pretty_cards");
|
hashSet.add("ads_post_pretty_cards");
|
||||||
hashSet.add("ads_post_snippet_video");
|
hashSet.add("ads_post_snippet_video");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static boolean isPowerSaveMode() {
|
||||||
|
var pw = (PowerManager) getGlobalContext().getSystemService(Context.POWER_SERVICE);
|
||||||
|
|
||||||
|
return !getBoolValue("force_disable_psm", false) && pw.isPowerSaveMode();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -135,7 +135,7 @@ public class PhotoViewer {
|
|||||||
if (attachment.J != null) {
|
if (attachment.J != null) {
|
||||||
imageSizes = attachment.J.t1();
|
imageSizes = attachment.J.t1();
|
||||||
}
|
}
|
||||||
return getUrlFromImageSizeList(imageSizes != null ? imageSizes : null);
|
return getUrlFromImageSizeList(imageSizes);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static String getUrlFromPhotoAttachment(PhotoAttachment attachment) {
|
private static String getUrlFromPhotoAttachment(PhotoAttachment attachment) {
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
package ru.vtosters.lite.hooks;
|
package ru.vtosters.lite.hooks;
|
||||||
|
|
||||||
import static ru.vtosters.lite.utils.Preferences.preferences;
|
import static ru.vtosters.lite.utils.Preferences.preferences;
|
||||||
|
|
||||||
import android.graphics.Bitmap;
|
import android.graphics.Bitmap;
|
||||||
@@ -12,7 +13,7 @@ import com.facebook.drawee.generic.RoundingParams;
|
|||||||
|
|
||||||
import ru.vtosters.lite.utils.AndroidUtils;
|
import ru.vtosters.lite.utils.AndroidUtils;
|
||||||
|
|
||||||
public class PicRoundingHook{
|
public class PicRoundingHook {
|
||||||
private static final int pref = preferences.getInt("pic_rounding", 0);
|
private static final int pref = preferences.getInt("pic_rounding", 0);
|
||||||
|
|
||||||
public static RoundingParams inject() {
|
public static RoundingParams inject() {
|
||||||
@@ -39,7 +40,7 @@ public class PicRoundingHook{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void inject(float orig, Canvas canvas, Paint paint){
|
public static void inject(float orig, Canvas canvas, Paint paint) {
|
||||||
if (pref > 0) {
|
if (pref > 0) {
|
||||||
canvas.drawRoundRect(new RectF(0, 0, canvas.getWidth(), canvas.getHeight()), AndroidUtils.dp2px(pref), AndroidUtils.dp2px(pref), paint);
|
canvas.drawRoundRect(new RectF(0, 0, canvas.getWidth(), canvas.getHeight()), AndroidUtils.dp2px(pref), AndroidUtils.dp2px(pref), paint);
|
||||||
} else {
|
} else {
|
||||||
@@ -47,7 +48,7 @@ public class PicRoundingHook{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void inject(Canvas canvas, Paint paint, float orig){
|
public static void inject(Canvas canvas, Paint paint, float orig) {
|
||||||
if (pref > 0) {
|
if (pref > 0) {
|
||||||
canvas.drawRoundRect(new RectF(0, 0, canvas.getWidth(), canvas.getHeight()), AndroidUtils.dp2px(pref), AndroidUtils.dp2px(pref), paint);
|
canvas.drawRoundRect(new RectF(0, 0, canvas.getWidth(), canvas.getHeight()), AndroidUtils.dp2px(pref), AndroidUtils.dp2px(pref), paint);
|
||||||
} else {
|
} else {
|
||||||
@@ -55,7 +56,7 @@ public class PicRoundingHook{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void inject(Canvas canvas, float orig, float orig2, float orig3, Paint paint){
|
public static void inject(Canvas canvas, float orig, float orig2, float orig3, Paint paint) {
|
||||||
if (pref > 0) {
|
if (pref > 0) {
|
||||||
canvas.drawRoundRect(new RectF(0, 0, canvas.getWidth(), canvas.getHeight()), AndroidUtils.dp2px(pref), AndroidUtils.dp2px(pref), paint);
|
canvas.drawRoundRect(new RectF(0, 0, canvas.getWidth(), canvas.getHeight()), AndroidUtils.dp2px(pref), AndroidUtils.dp2px(pref), paint);
|
||||||
} else {
|
} else {
|
||||||
@@ -76,7 +77,7 @@ public class PicRoundingHook{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static RoundingParams customParams(){
|
private static RoundingParams customParams() {
|
||||||
return RoundingParams.b(AndroidUtils.dp2px(pref), AndroidUtils.dp2px(pref), AndroidUtils.dp2px(pref), AndroidUtils.dp2px(pref));
|
return RoundingParams.b(AndroidUtils.dp2px(pref), AndroidUtils.dp2px(pref), AndroidUtils.dp2px(pref), AndroidUtils.dp2px(pref));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,7 +14,8 @@ import ru.vtosters.lite.utils.Preferences;
|
|||||||
public class PostViewHook {
|
public class PostViewHook {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* For displaying child elements with custom direction in rtl container we should remove their, set layout direction and add again */
|
* For displaying child elements with custom direction in rtl container we should remove their, set layout direction and add again
|
||||||
|
*/
|
||||||
private static void saveChildDirectionForRlt(ViewGroup container) {
|
private static void saveChildDirectionForRlt(ViewGroup container) {
|
||||||
var children = new View[container.getChildCount()];
|
var children = new View[container.getChildCount()];
|
||||||
for (int i = 0; i < container.getChildCount(); i++) {
|
for (int i = 0; i < container.getChildCount(); i++) {
|
||||||
|
|||||||
@@ -6,27 +6,25 @@ import static ru.vtosters.lite.proxy.ProxyUtils.isZaboronaEnabled;
|
|||||||
import static ru.vtosters.lite.utils.AndroidUtils.dp2px;
|
import static ru.vtosters.lite.utils.AndroidUtils.dp2px;
|
||||||
import static ru.vtosters.lite.utils.AndroidUtils.edit;
|
import static ru.vtosters.lite.utils.AndroidUtils.edit;
|
||||||
import static ru.vtosters.lite.utils.LifecycleUtils.restartApplication;
|
import static ru.vtosters.lite.utils.LifecycleUtils.restartApplication;
|
||||||
import static ru.vtosters.lite.utils.ThemesUtils.getAccentColor;
|
|
||||||
import static ru.vtosters.lite.utils.ThemesUtils.getAlertStyle;
|
|
||||||
import static ru.vtosters.lite.utils.ThemesUtils.getTextAttr;
|
import static ru.vtosters.lite.utils.ThemesUtils.getTextAttr;
|
||||||
|
|
||||||
import android.annotation.SuppressLint;
|
import android.annotation.SuppressLint;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.DialogInterface;
|
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.util.TypedValue;
|
import android.util.TypedValue;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.widget.RadioButton;
|
import android.widget.RadioButton;
|
||||||
import android.widget.RadioGroup;
|
import android.widget.RadioGroup;
|
||||||
|
|
||||||
import androidx.appcompat.app.AlertDialog;
|
|
||||||
import androidx.appcompat.view.ContextThemeWrapper;
|
import androidx.appcompat.view.ContextThemeWrapper;
|
||||||
|
|
||||||
import com.vk.auth.ui.VkAuthTextView;
|
import com.vk.auth.ui.VkAuthTextView;
|
||||||
|
import com.vk.core.dialogs.alert.VkAlertDialog;
|
||||||
import com.vk.navigation.Navigator;
|
import com.vk.navigation.Navigator;
|
||||||
|
|
||||||
import ru.vtosters.lite.ui.fragments.ProxySettingsFragment;
|
import ru.vtosters.lite.ui.fragments.ProxySettingsFragment;
|
||||||
import ru.vtosters.lite.utils.AndroidUtils;
|
import ru.vtosters.lite.utils.AndroidUtils;
|
||||||
|
import ru.vtosters.lite.utils.ThemesUtils;
|
||||||
|
|
||||||
public class ProxyHook {
|
public class ProxyHook {
|
||||||
public static void hookAuth(View v) {
|
public static void hookAuth(View v) {
|
||||||
@@ -73,37 +71,31 @@ public class ProxyHook {
|
|||||||
rgRandomProxy.setChecked(isRandomProxyEnabled());
|
rgRandomProxy.setChecked(isRandomProxyEnabled());
|
||||||
rgVika.setChecked(isVikaProxyEnabled());
|
rgVika.setChecked(isVikaProxyEnabled());
|
||||||
|
|
||||||
AlertDialog.Builder builder = new AlertDialog.Builder(ctx, getAlertStyle());
|
new VkAlertDialog.Builder(ctx)
|
||||||
builder.setTitle(AndroidUtils.getString("vtlproxy"));
|
.setTitle(AndroidUtils.getString("vtlproxy"))
|
||||||
builder.setMessage(AndroidUtils.getString("proxy_warning"));
|
.setMessage(AndroidUtils.getString("proxy_warning"))
|
||||||
builder.setView(rg);
|
.setView(rg)
|
||||||
builder.setPositiveButton(AndroidUtils.getString("vtl_confirm"), ((dialog, which) -> { // Применить
|
.setPositiveButton(AndroidUtils.getString("vtl_confirm"), ((dialog, which) -> { // Применить
|
||||||
if (rgZaborona.isChecked()) {
|
if (rgZaborona.isChecked()) {
|
||||||
edit().putString("proxy", "zaborona").commit();
|
edit().putString("proxy", "zaborona").commit();
|
||||||
restartApplication();
|
restartApplication();
|
||||||
} else if (rgRandomProxy.isChecked()) {
|
} else if (rgRandomProxy.isChecked()) {
|
||||||
edit().putString("proxy", "randomproxy").commit();
|
edit().putString("proxy", "randomproxy").commit();
|
||||||
restartApplication();
|
restartApplication();
|
||||||
} else if (rgVika.isChecked()) {
|
} else if (rgVika.isChecked()) {
|
||||||
edit().putString("proxy", "vika").commit();
|
edit().putString("proxy", "vika").commit();
|
||||||
restartApplication();
|
restartApplication();
|
||||||
} else {
|
} else {
|
||||||
edit().putString("proxy", "noproxy").commit();
|
edit().putString("proxy", "noproxy").commit();
|
||||||
restartApplication();
|
restartApplication();
|
||||||
}
|
}
|
||||||
}));
|
}))
|
||||||
|
.setNeutralButton(AndroidUtils.getString("proxy_settings"), ((dialog, which) -> {
|
||||||
builder.setNeutralButton(AndroidUtils.getString("proxy_settings"), ((dialog, which) -> {
|
var intent = new Navigator(ProxySettingsFragment.class)
|
||||||
Intent a2 = new Navigator(ProxySettingsFragment.class).b(ctx);
|
.b(ctx)
|
||||||
a2.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||||
ctx.startActivity(a2);
|
ctx.startActivity(intent);
|
||||||
}));
|
}))
|
||||||
|
.show();
|
||||||
var alert = builder.create();
|
|
||||||
|
|
||||||
alert.show();
|
|
||||||
|
|
||||||
alert.getButton(DialogInterface.BUTTON_POSITIVE).setTextColor(getAccentColor());
|
|
||||||
alert.getButton(DialogInterface.BUTTON_NEUTRAL).setTextColor(getAccentColor());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
package ru.vtosters.lite.hooks;
|
package ru.vtosters.lite.hooks;
|
||||||
|
|
||||||
import static ru.vtosters.lite.utils.Preferences.dev;
|
import static ru.vtosters.lite.utils.Preferences.dev;
|
||||||
|
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
@@ -7,9 +8,9 @@ import com.vk.api.internal.MethodCall;
|
|||||||
|
|
||||||
import java.util.LinkedHashMap;
|
import java.util.LinkedHashMap;
|
||||||
|
|
||||||
public class RequestDumper{
|
public class RequestDumper {
|
||||||
public static void addParams(MethodCall.a paramslist, String method, LinkedHashMap<String, String> params, String apiver) {
|
public static void addParams(MethodCall.a paramslist, String method, LinkedHashMap<String, String> params, String apiver) {
|
||||||
if (method.contains("execute.getGiftByStickerId") ) {
|
if (method.contains("execute.getGiftByStickerId")) {
|
||||||
apiver = "5.186";
|
apiver = "5.186";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ package ru.vtosters.lite.hooks;
|
|||||||
|
|
||||||
import static ru.vtosters.lite.ui.components.DockBarEditorManager.getInstance;
|
import static ru.vtosters.lite.ui.components.DockBarEditorManager.getInstance;
|
||||||
import static ru.vtosters.lite.utils.AndroidUtils.getPrefsValue;
|
import static ru.vtosters.lite.utils.AndroidUtils.getPrefsValue;
|
||||||
import static ru.vtosters.lite.utils.Preferences.getBoolValue;
|
|
||||||
import static ru.vtosters.lite.utils.Preferences.milkshake;
|
import static ru.vtosters.lite.utils.Preferences.milkshake;
|
||||||
import static ru.vtosters.lite.utils.Preferences.superapp;
|
import static ru.vtosters.lite.utils.Preferences.superapp;
|
||||||
import static ru.vtosters.lite.utils.Preferences.useNewSettings;
|
import static ru.vtosters.lite.utils.Preferences.useNewSettings;
|
||||||
@@ -28,7 +27,6 @@ import com.vtosters.lite.fragments.p2.DocumentsViewFragment;
|
|||||||
import com.vtosters.lite.fragments.s2.GroupsFragment1;
|
import com.vtosters.lite.fragments.s2.GroupsFragment1;
|
||||||
import com.vtosters.lite.fragments.t2.c.DialogsFragment;
|
import com.vtosters.lite.fragments.t2.c.DialogsFragment;
|
||||||
import com.vtosters.lite.fragments.y2.VideoCatalogFragment;
|
import com.vtosters.lite.fragments.y2.VideoCatalogFragment;
|
||||||
import com.vtosters.lite.fragments.y2.VideosFragment;
|
|
||||||
import com.vtosters.lite.general.fragments.GamesFragment;
|
import com.vtosters.lite.general.fragments.GamesFragment;
|
||||||
import com.vtosters.lite.general.fragments.PhotosFragment;
|
import com.vtosters.lite.general.fragments.PhotosFragment;
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,16 @@
|
|||||||
|
package ru.vtosters.lite.hooks;
|
||||||
|
|
||||||
|
import static ru.vtosters.lite.utils.Preferences.wbios;
|
||||||
|
|
||||||
|
import ru.vtosters.lite.utils.AndroidUtils;
|
||||||
|
import ru.vtosters.lite.utils.ThemesUtils;
|
||||||
|
|
||||||
|
public class WritebarHook {
|
||||||
|
public static int getWriteBar() {
|
||||||
|
return AndroidUtils.getIdentifier((wbios() ? "write_bar_i" : "write_bar"), "layout");
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int getIconsColors(int def) {
|
||||||
|
return wbios() ? ThemesUtils.getAccentColor() : def;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,6 +1,16 @@
|
|||||||
package ru.vtosters.lite.hooks.ui;
|
package ru.vtosters.lite.hooks.ui;
|
||||||
|
|
||||||
import android.util.Log;
|
import static bruhcollective.itaysonlab.libvkx.client.LibVKXClient.asId;
|
||||||
|
import static bruhcollective.itaysonlab.libvkx.client.LibVKXClient.getInstance;
|
||||||
|
import static bruhcollective.itaysonlab.libvkx.client.LibVKXClient.isIntegrationEnabled;
|
||||||
|
import static bruhcollective.itaysonlab.libvkx.client.LibVKXClient.isVkxInstalled;
|
||||||
|
import static bruhcollective.itaysonlab.libvkx.client.LibVKXClient.lambdaplay;
|
||||||
|
import static ru.vtosters.lite.music.cache.CacheDatabaseDelegate.isCached;
|
||||||
|
import static ru.vtosters.lite.music.cache.CacheDatabaseDelegate.isVkxCached;
|
||||||
|
import static ru.vtosters.lite.utils.NetworkUtils.isNetworkConnected;
|
||||||
|
import static ru.vtosters.lite.utils.Preferences.milkshake;
|
||||||
|
|
||||||
|
import android.os.RemoteException;
|
||||||
|
|
||||||
import com.vk.dto.music.MusicTrack;
|
import com.vk.dto.music.MusicTrack;
|
||||||
import com.vk.dto.music.Playlist;
|
import com.vk.dto.music.Playlist;
|
||||||
@@ -9,24 +19,180 @@ import com.vk.music.common.MusicPlaybackLaunchContext;
|
|||||||
import com.vtosters.lite.R;
|
import com.vtosters.lite.R;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.concurrent.ExecutorService;
|
||||||
|
import java.util.concurrent.Executors;
|
||||||
|
|
||||||
import bruhcollective.itaysonlab.libvkx.client.LibVKXClient;
|
|
||||||
import bruhcollective.itaysonlab.libvkx.client.LibVKXClientImpl;
|
import bruhcollective.itaysonlab.libvkx.client.LibVKXClientImpl;
|
||||||
|
import ru.vtosters.lite.downloaders.AudioDownloader;
|
||||||
import ru.vtosters.lite.utils.AndroidUtils;
|
import ru.vtosters.lite.utils.AndroidUtils;
|
||||||
|
|
||||||
public class MusicBottomSheetHook {
|
public class MusicBottomSheetHook {
|
||||||
public static ArrayList<MusicAction> hook(ArrayList<MusicAction> actions) {
|
private static final ExecutorService executor = Executors.newCachedThreadPool();
|
||||||
if (LibVKXClient.isVkxInstalled()) {
|
|
||||||
|
public static ArrayList<MusicAction> hook(ArrayList<MusicAction> actions, MusicTrack musicTrack) {
|
||||||
|
if (musicTrack.F1()) return actions;
|
||||||
|
|
||||||
|
var trackid = asId(musicTrack);
|
||||||
|
|
||||||
|
if (isVkxInstalled()) {
|
||||||
actions.add(getPlayInVKXAction());
|
actions.add(getPlayInVKXAction());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (isIntegrationEnabled()) {
|
||||||
|
if (isVkxCached(trackid)) {
|
||||||
|
actions.add(getRemoveCacheTrackVkxAction());
|
||||||
|
} else {
|
||||||
|
actions.add(addToCacheTrackVkxAction());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isNetworkConnected()) {
|
||||||
|
actions.add(downloadAsMp3Action());
|
||||||
|
}
|
||||||
|
|
||||||
return actions;
|
return actions;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean tryPlayInVKX(int actionId, MusicTrack track, MusicPlaybackLaunchContext context, Playlist playlist) {
|
|
||||||
if (actionId != AndroidUtils.getIdentifier("play_in_vkx", "id")) {
|
public static ArrayList<MusicAction> hookDownloadBTN(ArrayList<MusicAction> actions, MusicTrack musicTrack) {
|
||||||
return false;
|
if (musicTrack.F1()) return actions;
|
||||||
|
|
||||||
|
var trackid = asId(musicTrack);
|
||||||
|
|
||||||
|
if (isCached(trackid)) {
|
||||||
|
actions.add(new MusicAction(
|
||||||
|
AndroidUtils.getIdentifier("music_action_toggle_download", "id"),
|
||||||
|
milkshake() ? R.drawable.ic_delete_outline_28 : R.drawable.ic_delete_24,
|
||||||
|
AndroidUtils.getIdentifier("remove_from_cache", "string"),
|
||||||
|
musicTrack.F1() ? R.color.music_action_button_gray_50_alpha : R.color.caption_gray,
|
||||||
|
R.string.music_talkback_empty,
|
||||||
|
false
|
||||||
|
));
|
||||||
|
} else {
|
||||||
|
actions.add(new MusicAction(
|
||||||
|
AndroidUtils.getIdentifier("music_action_toggle_download", "id"),
|
||||||
|
milkshake() ? R.drawable.ic_download_outline_28 : R.drawable.ic_download_24,
|
||||||
|
AndroidUtils.getIdentifier("add_to_cache", "string"),
|
||||||
|
musicTrack.F1() ? R.color.music_action_button_gray_50_alpha : R.color.caption_gray,
|
||||||
|
R.string.music_talkback_empty,
|
||||||
|
false
|
||||||
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return actions;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ArrayList<MusicAction> hook(ArrayList<MusicAction> actions, Playlist playlist) {
|
||||||
|
if (playlist.D) return actions;
|
||||||
|
|
||||||
|
if (isVkxInstalled()) actions.add(getPlayInVKXAction());
|
||||||
|
|
||||||
|
if (isIntegrationEnabled()) {
|
||||||
|
if (isVkxCached(playlist.a, playlist.b)) {
|
||||||
|
actions.add(getRemoveCacheTrackVkxAction());
|
||||||
|
} else {
|
||||||
|
actions.add(addToCacheTrackVkxAction());
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
actions.add(addToCacheTrackAction());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isNetworkConnected()) actions.add(downloadAsMp3Action());
|
||||||
|
|
||||||
|
return actions;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean injectOnClick(int actionId, MusicTrack track, MusicPlaybackLaunchContext context, Playlist playlist) { // musictrack inj
|
||||||
|
if (actionId == AndroidUtils.getIdentifier("play_in_vkx", "id"))
|
||||||
|
return tryPlayInVKX(track, context, playlist);
|
||||||
|
|
||||||
|
if (actionId == AndroidUtils.getIdentifier("remove_from_cache_vkx", "id")) {
|
||||||
|
getInstance().runOnService(service -> {
|
||||||
|
try {
|
||||||
|
service.deleteTrackFromCache(track.d, track.e);
|
||||||
|
} catch (RemoteException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return true;
|
||||||
|
} else if (actionId == AndroidUtils.getIdentifier("add_to_cache_vkx", "id")) {
|
||||||
|
getInstance().runOnService(service -> {
|
||||||
|
try {
|
||||||
|
service.addTrackToCache(track.d, track.e, (track.J != null) ? track.J : "");
|
||||||
|
} catch (RemoteException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (actionId == AndroidUtils.getIdentifier("download_mp3", "id")) {
|
||||||
|
if (isIntegrationEnabled()) {
|
||||||
|
getInstance().runOnService(service -> {
|
||||||
|
try {
|
||||||
|
service.downloadTrack(track.d, track.e, (track.J != null) ? track.J : "");
|
||||||
|
} catch (RemoteException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
AudioDownloader.downloadAudio(track);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean injectOnClick(int actionId, Playlist playlist) { // playlist inj
|
||||||
|
if (actionId == AndroidUtils.getIdentifier("play_in_vkx", "id"))
|
||||||
|
return tryPlayInVKX(null, null, playlist);
|
||||||
|
|
||||||
|
if (actionId == AndroidUtils.getIdentifier("add_to_cache", "id")) {
|
||||||
|
executor.submit(() -> AudioDownloader.cachePlaylist(playlist));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (actionId == AndroidUtils.getIdentifier("remove_from_cache_vkx", "id")) {
|
||||||
|
getInstance().runOnService(service -> {
|
||||||
|
try {
|
||||||
|
service.deletePlaylistFromCache(playlist.a, playlist.b);
|
||||||
|
} catch (RemoteException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return true;
|
||||||
|
} else if (actionId == AndroidUtils.getIdentifier("add_to_cache_vkx", "id")) {
|
||||||
|
getInstance().runOnService(service -> {
|
||||||
|
try {
|
||||||
|
service.addPlaylistToCache(playlist.a, playlist.b, (playlist.Q != null) ? playlist.Q : "");
|
||||||
|
} catch (RemoteException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (actionId == AndroidUtils.getIdentifier("download_mp3", "id")) {
|
||||||
|
if (isIntegrationEnabled()) {
|
||||||
|
getInstance().runOnService(service -> {
|
||||||
|
try {
|
||||||
|
service.downloadPlaylist(playlist.a, playlist.b, (playlist.Q != null) ? playlist.Q : "");
|
||||||
|
} catch (RemoteException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
executor.submit(() -> AudioDownloader.downloadPlaylist(playlist));
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean tryPlayInVKX(MusicTrack track, MusicPlaybackLaunchContext context, Playlist playlist) {
|
||||||
var trackList = new ArrayList<MusicTrack>();
|
var trackList = new ArrayList<MusicTrack>();
|
||||||
|
|
||||||
if (playlist != null) {
|
if (playlist != null) {
|
||||||
@@ -35,18 +201,73 @@ public class MusicBottomSheetHook {
|
|||||||
trackList.add(track);
|
trackList.add(track);
|
||||||
}
|
}
|
||||||
|
|
||||||
LibVKXClientImpl.LibVKXAction action = iLibVkxService -> LibVKXClient.lambdaplay(trackList, track, iLibVkxService, context);
|
LibVKXClientImpl.LibVKXAction action = iLibVkxService -> lambdaplay(trackList, track, iLibVkxService, context);
|
||||||
return LibVKXClient.getInstance().runOnService(action);
|
return getInstance().runOnService(action);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static MusicAction getPlayInVKXAction() {
|
private static MusicAction getPlayInVKXAction() {
|
||||||
return new MusicAction(
|
return new MusicAction(
|
||||||
AndroidUtils.getIdentifier("play_in_vkx", "id"),
|
AndroidUtils.getIdentifier("play_in_vkx", "id"),
|
||||||
R.drawable.ic_music_24,
|
milkshake() ? R.drawable.ic_music_outline_24 : R.drawable.ic_music_24,
|
||||||
AndroidUtils.getIdentifier("play_in_vkx", "string"),
|
AndroidUtils.getIdentifier("play_in_vkx", "string"),
|
||||||
R.color.caption_gray,
|
R.color.caption_gray,
|
||||||
R.string.music_talkback_empty,
|
R.string.music_talkback_empty,
|
||||||
false
|
false
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static MusicAction getRemoveCacheTrackAction() {
|
||||||
|
return new MusicAction(
|
||||||
|
AndroidUtils.getIdentifier("remove_from_cache", "id"),
|
||||||
|
milkshake() ? R.drawable.ic_delete_outline_28 : R.drawable.ic_delete_24,
|
||||||
|
AndroidUtils.getIdentifier("remove_from_cache", "string"),
|
||||||
|
R.color.caption_gray,
|
||||||
|
R.string.music_talkback_empty,
|
||||||
|
false
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static MusicAction addToCacheTrackAction() {
|
||||||
|
return new MusicAction(
|
||||||
|
AndroidUtils.getIdentifier("add_to_cache", "id"),
|
||||||
|
milkshake() ? R.drawable.ic_add_outline_28 : R.drawable.ic_add_24,
|
||||||
|
AndroidUtils.getIdentifier("add_to_cache", "string"),
|
||||||
|
R.color.caption_gray,
|
||||||
|
R.string.music_talkback_empty,
|
||||||
|
false
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static MusicAction getRemoveCacheTrackVkxAction() {
|
||||||
|
return new MusicAction(
|
||||||
|
AndroidUtils.getIdentifier("remove_from_cache_vkx", "id"),
|
||||||
|
milkshake() ? R.drawable.ic_delete_outline_28 : R.drawable.ic_delete_24,
|
||||||
|
AndroidUtils.getIdentifier("remove_from_cache_vkx", "string"),
|
||||||
|
R.color.caption_gray,
|
||||||
|
R.string.music_talkback_empty,
|
||||||
|
false
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static MusicAction addToCacheTrackVkxAction() {
|
||||||
|
return new MusicAction(
|
||||||
|
AndroidUtils.getIdentifier("add_to_cache_vkx", "id"),
|
||||||
|
milkshake() ? R.drawable.ic_add_outline_28 : R.drawable.ic_add_24,
|
||||||
|
AndroidUtils.getIdentifier("add_to_cache_vkx", "string"),
|
||||||
|
R.color.caption_gray,
|
||||||
|
R.string.music_talkback_empty,
|
||||||
|
false
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static MusicAction downloadAsMp3Action() {
|
||||||
|
return new MusicAction(
|
||||||
|
AndroidUtils.getIdentifier("download_mp3", "id"),
|
||||||
|
milkshake() ? R.drawable.ic_download_outline_28 : R.drawable.ic_download_24,
|
||||||
|
AndroidUtils.getIdentifier("download_mp3", "string"),
|
||||||
|
R.color.caption_gray,
|
||||||
|
R.string.music_talkback_empty,
|
||||||
|
false
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,17 +6,24 @@ import ru.vtosters.lite.utils.Preferences;
|
|||||||
import ru.vtosters.lite.utils.ThemesUtils;
|
import ru.vtosters.lite.utils.ThemesUtils;
|
||||||
|
|
||||||
public class SystemThemeChangerHook {
|
public class SystemThemeChangerHook {
|
||||||
|
private static int latestTheme = 0;
|
||||||
|
|
||||||
public static void onThemeChanged(Configuration configuration) {
|
public static void onThemeChanged(Configuration configuration) {
|
||||||
if (Preferences.systemtheme()) {
|
if (Preferences.systemtheme()) {
|
||||||
switch (configuration.uiMode & Configuration.UI_MODE_NIGHT_MASK) {
|
var theme = configuration.uiMode & Configuration.UI_MODE_NIGHT_MASK;
|
||||||
|
if (theme == latestTheme) return;
|
||||||
|
|
||||||
|
switch (theme) {
|
||||||
case Configuration.UI_MODE_NIGHT_YES:
|
case Configuration.UI_MODE_NIGHT_YES:
|
||||||
// Night mode is active, we're using dark theme
|
// Night mode is active, we're using dark theme
|
||||||
ThemesUtils.applyTheme(ThemesUtils.getDarkTheme());
|
ThemesUtils.applyTheme(ThemesUtils.getDarkTheme());
|
||||||
|
latestTheme = theme;
|
||||||
break;
|
break;
|
||||||
case Configuration.UI_MODE_NIGHT_NO:
|
case Configuration.UI_MODE_NIGHT_NO:
|
||||||
case Configuration.UI_MODE_NIGHT_UNDEFINED:
|
case Configuration.UI_MODE_NIGHT_UNDEFINED:
|
||||||
// Night mode is not active, we're using light theme
|
// Night mode is not active, we're using light theme
|
||||||
ThemesUtils.applyTheme(ThemesUtils.getLightTheme());
|
ThemesUtils.applyTheme(ThemesUtils.getLightTheme());
|
||||||
|
latestTheme = theme;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
package ru.vtosters.lite.music;
|
package ru.vtosters.lite.music;
|
||||||
|
|
||||||
import android.util.Log;
|
import com.vk.dto.music.MusicTrack;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
@@ -8,63 +8,120 @@ import java.io.InputStream;
|
|||||||
import java.security.InvalidAlgorithmParameterException;
|
import java.security.InvalidAlgorithmParameterException;
|
||||||
import java.security.InvalidKeyException;
|
import java.security.InvalidKeyException;
|
||||||
import java.security.NoSuchAlgorithmException;
|
import java.security.NoSuchAlgorithmException;
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
|
|
||||||
import javax.crypto.NoSuchPaddingException;
|
import javax.crypto.NoSuchPaddingException;
|
||||||
|
|
||||||
|
import java8.util.concurrent.CompletableFuture;
|
||||||
import okhttp3.Call;
|
import okhttp3.Call;
|
||||||
import okhttp3.OkHttpClient;
|
import okhttp3.OkHttpClient;
|
||||||
import okhttp3.Request;
|
import okhttp3.Request;
|
||||||
import okhttp3.Response;
|
import okhttp3.Response;
|
||||||
|
import ru.vtosters.lite.music.converter.ts.FFMpeg;
|
||||||
|
import ru.vtosters.lite.music.converter.ts.TSMerger;
|
||||||
|
import ru.vtosters.lite.music.downloader.ThumbnailDownloader;
|
||||||
|
import ru.vtosters.lite.music.interfaces.ITrackDownloader;
|
||||||
import ru.vtosters.lite.utils.IOUtils;
|
import ru.vtosters.lite.utils.IOUtils;
|
||||||
|
|
||||||
public class M3UDownloader {
|
public class M3UDownloader implements ITrackDownloader {
|
||||||
|
private static final OkHttpClient client = new OkHttpClient();
|
||||||
|
|
||||||
private static OkHttpClient client = new OkHttpClient();
|
public static M3UDownloader getInstance() {
|
||||||
|
return Holder.INSTANCE;
|
||||||
|
}
|
||||||
|
|
||||||
public static void execute(String url, File outDir, Callback callback) {
|
public void downloadTrack(MusicTrack track, File outDir, Callback callback, boolean cache) {
|
||||||
var request = new Request.a()
|
var request = new Request.a()
|
||||||
.b(url)
|
.b(track.D)
|
||||||
.a();
|
.a();
|
||||||
client.a(request).a(new okhttp3.Callback() {
|
client.a(request).a(new okhttp3.Callback() {
|
||||||
@Override
|
@Override
|
||||||
public void a(Call call, IOException e) {
|
public void a(Call call, IOException e) {
|
||||||
|
callback.onFailure();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void a(Call call, Response response) throws IOException {
|
public void a(Call call, Response response) throws IOException {
|
||||||
parse(response.a().g(), outDir, callback);
|
parse(response.a().g(), outDir, callback, track, cache);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void parse(String payload, File outDir, Callback callback) {
|
private void parse(String payload, File outDir, Callback callback, MusicTrack track, boolean cache) {
|
||||||
try {
|
if (cache)
|
||||||
VKM3UParser parser = new VKM3UParser(payload);
|
try {
|
||||||
List<TransportStream> tses = parser.getTransportStreams();
|
ThumbnailDownloader.downloadThumbnails(track);
|
||||||
callback.onProgress(5);
|
} catch (IOException e) {
|
||||||
for (TransportStream ts : tses) {
|
e.printStackTrace();
|
||||||
String tsURL = parser.getBaseUrl() + ts.getName();
|
}
|
||||||
Log.d("M3UDownloader", "Downloading " + tsURL);
|
|
||||||
InputStream is = IOUtils.openStream(tsURL);
|
VKM3UParser parser = new VKM3UParser(payload);
|
||||||
byte[] content;
|
List<TransportStream> tses = parser.getTransportStreams();
|
||||||
if (TransportStream.METHOD_AES128.equals(ts.getMethod())) {
|
AtomicInteger progress = new AtomicInteger(0);
|
||||||
String key = IOUtils.readAllLines(IOUtils.openStream(ts.getKeyURL()));
|
List<CompletableFuture<Void>> futures = new ArrayList<>();
|
||||||
content = IOUtils.decodeStream(is, key);
|
|
||||||
} else {
|
var tsesDir = new File(outDir, String.valueOf(track.d));
|
||||||
content = IOUtils.readAllBytes(is);
|
tsesDir.mkdirs();
|
||||||
}
|
var resultTs = new File(tsesDir, "result.ts");
|
||||||
File tsDump = new File(outDir, ts.getName());
|
|
||||||
IOUtils.writeToFile(tsDump, content);
|
String title = null;
|
||||||
callback.onSizeReceived((long) content.length * tses.size(), parser.getHeapSize());
|
|
||||||
callback.onProgress(10 + Math.round(80.0f * tses.indexOf(ts) / tses.size()));
|
if (track.f != null) {
|
||||||
|
title = track.f;
|
||||||
|
if (!track.g.isEmpty()) {
|
||||||
|
title += " (" + track.g + ")";
|
||||||
}
|
}
|
||||||
} catch (IOException | NoSuchPaddingException | NoSuchAlgorithmException | InvalidAlgorithmParameterException | InvalidKeyException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
callback.onFailure();
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
callback.onSuccess();
|
|
||||||
|
var fileName = IOUtils.getValidFileName((cache ? "track" : track.C + " - " + title) + ".mp3");
|
||||||
|
var resultMp3 = new File(outDir, fileName);
|
||||||
|
|
||||||
|
callback.onProgress(5);
|
||||||
|
for (TransportStream ts : tses) {
|
||||||
|
String tsURL = parser.getBaseUrl() + ts.getName();
|
||||||
|
|
||||||
|
futures.add(CompletableFuture.runAsync(() -> {
|
||||||
|
try {
|
||||||
|
InputStream is = IOUtils.openStream(tsURL);
|
||||||
|
byte[] content;
|
||||||
|
if (TransportStream.METHOD_AES128.equals(ts.getMethod())) {
|
||||||
|
String key = IOUtils.readAllLines(IOUtils.openStream(ts.getKeyURL()));
|
||||||
|
content = IOUtils.decodeStream(is, key);
|
||||||
|
} else {
|
||||||
|
content = IOUtils.readAllBytes(is);
|
||||||
|
}
|
||||||
|
File tsDump = new File(tsesDir, ts.getName());
|
||||||
|
IOUtils.writeToFile(tsDump, content);
|
||||||
|
callback.onProgress(10 + Math.round(80.0f * progress.addAndGet(1) / tses.size()));
|
||||||
|
callback.onSizeReceived((long) content.length * tses.size(), parser.getHeapSize());
|
||||||
|
} catch (IOException | NoSuchPaddingException | NoSuchAlgorithmException |
|
||||||
|
InvalidAlgorithmParameterException | InvalidKeyException e) {
|
||||||
|
callback.onFailure();
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
var future = CompletableFuture.allOf(futures.toArray(new CompletableFuture[0]));
|
||||||
|
future.exceptionally(throwable -> {
|
||||||
|
callback.onFailure();
|
||||||
|
return null;
|
||||||
|
})
|
||||||
|
.thenApply(v -> TSMerger.merge(tsesDir, resultTs))
|
||||||
|
.thenApply(mergeResult -> mergeResult && FFMpeg.convert(resultTs, resultMp3.getAbsolutePath(), track))
|
||||||
|
.thenApply(convertResult -> {
|
||||||
|
if (convertResult)
|
||||||
|
callback.onProgress(10 + Math.round(80.0f * progress.addAndGet(1) / tses.size()));
|
||||||
|
else callback.onFailure();
|
||||||
|
return convertResult;
|
||||||
|
})
|
||||||
|
.thenRun(() -> IOUtils.deleteRecursive(tsesDir))
|
||||||
|
.thenRun(callback::onSuccess);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Initialization-on-demand
|
||||||
|
private static class Holder {
|
||||||
|
private static final M3UDownloader INSTANCE = new M3UDownloader();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,87 +1,76 @@
|
|||||||
package ru.vtosters.lite.music;
|
//package ru.vtosters.lite.music;
|
||||||
|
//
|
||||||
import static ru.vtosters.lite.proxy.ProxyUtils.getApi;
|
//import android.text.TextUtils;
|
||||||
|
//import android.util.Log;
|
||||||
import android.app.DownloadManager;
|
//import android.widget.Toast;
|
||||||
import android.net.Uri;
|
//
|
||||||
import android.os.Build;
|
//import com.vk.dto.music.MusicTrack;
|
||||||
import android.os.Environment;
|
//
|
||||||
import android.util.Log;
|
//import org.json.JSONException;
|
||||||
import android.widget.Toast;
|
//import org.json.JSONObject;
|
||||||
|
//
|
||||||
import androidx.annotation.RequiresApi;
|
//import java.io.File;
|
||||||
|
//import java.io.IOException;
|
||||||
import com.vk.dto.music.MusicTrack;
|
//
|
||||||
|
//import okhttp3.Call;
|
||||||
import org.json.JSONException;
|
//import okhttp3.Callback;
|
||||||
import org.json.JSONObject;
|
//import okhttp3.OkHttpClient;
|
||||||
|
//import okhttp3.Request;
|
||||||
import java.io.IOException;
|
//import okhttp3.Response;
|
||||||
|
//import ru.vtosters.lite.downloaders.AudioDownloader;
|
||||||
import okhttp3.Call;
|
//import ru.vtosters.lite.music.interfaces.ITrackDownloader;
|
||||||
import okhttp3.Callback;
|
//import ru.vtosters.lite.utils.AndroidUtils;
|
||||||
import okhttp3.OkHttpClient;
|
//
|
||||||
import okhttp3.Request;
|
//public class MP3Downloader implements ITrackDownloader {
|
||||||
import okhttp3.Response;
|
// private static final String URL_FORMAT = "https://api.vk.com/method/audio.getById?v=5.131&access_token=%s&audios=%s©right=";
|
||||||
import ru.vtosters.lite.downloaders.AudioDownloader;
|
//
|
||||||
import ru.vtosters.lite.utils.AndroidUtils;
|
// private static final OkHttpClient client = new OkHttpClient();
|
||||||
|
//
|
||||||
public class MP3Downloader {
|
// public static void downloadMP3(MusicTrack track) {
|
||||||
|
// var token = AndroidUtils.getPreferences().getString("vk_admin_token", "");
|
||||||
private static final String URL_FORMAT = "https://" + getApi() + "/method/audio.getById?v=5.131&access_token=%s&audios=%s©right=https://vtosters.app/";
|
// if (token.isEmpty()) {
|
||||||
private static final OkHttpClient client = new OkHttpClient();
|
// Toast.makeText(AndroidUtils.getGlobalContext(), "Обновите токен VK Admin в настройках", Toast.LENGTH_SHORT).show();
|
||||||
|
// return;
|
||||||
public static void execute(MusicTrack track) {
|
// }
|
||||||
var token = AndroidUtils.getPreferences().getString("vk_admin_token", "");
|
//
|
||||||
if (token.isEmpty()) {
|
// var request = new Request.a()
|
||||||
Toast.makeText(AndroidUtils.getGlobalContext(), AndroidUtils.getString("update_vk_admin_token"), Toast.LENGTH_SHORT).show();
|
// .b(String.format(URL_FORMAT, token, track.y1()))
|
||||||
return;
|
// .a();
|
||||||
}
|
// client.a(request).a(new Callback() {
|
||||||
var request = new Request.a()
|
// @Override
|
||||||
.b(String.format(URL_FORMAT, token, track.y1()))
|
// public void a(Call call, IOException e) {
|
||||||
.a();
|
// Log.d("MP3Downloader", e + "");
|
||||||
client.a(request).a(new Callback() {
|
// }
|
||||||
@Override
|
//
|
||||||
public void a(Call call, IOException e) {
|
// @Override
|
||||||
Log.d("MP3Downloader", e + "");
|
// public void a(Call call, Response response) throws IOException {
|
||||||
}
|
// var payload = response.a().g();
|
||||||
|
// Log.d("MP3Downloader", payload);
|
||||||
@Override
|
// try {
|
||||||
public void a(Call call, Response response) throws IOException {
|
// JSONObject jsonObj = new JSONObject(payload);
|
||||||
var payload = response.a().g();
|
// if (!jsonObj.has("response"))
|
||||||
Log.d("MP3Downloader", payload);
|
// return;
|
||||||
try {
|
// JSONObject responseNode = new JSONObject(payload).getJSONArray("response")
|
||||||
JSONObject jsonObj = new JSONObject(payload);
|
// .getJSONObject(0);
|
||||||
if (jsonObj.has("response")) {
|
// if (!responseNode.has("url"))
|
||||||
JSONObject responseNode = new JSONObject(payload).getJSONArray("response")
|
// return;
|
||||||
.getJSONObject(0);
|
// var url = responseNode.optString("url");
|
||||||
if (responseNode.has("url")) {
|
// Log.d("MP3Downloader", url);
|
||||||
var url = responseNode.optString("url");
|
// if (TextUtils.isEmpty(url))
|
||||||
Log.d("MP3Downloader", url);
|
// return;
|
||||||
if (url.endsWith(".mp3")) {
|
// if (VKM3UParser.isM3U8(url)) {
|
||||||
downloadMP3(track.toString(), url);
|
// AudioDownloader.downloadM3U8(track);
|
||||||
} else if (VKM3UParser.isM3U8(url)) {
|
// return;
|
||||||
AudioDownloader.downloadM3U8(track);
|
// }
|
||||||
}
|
// } catch (JSONException e) {
|
||||||
}
|
// Log.d("MP3Downloader", e + "");
|
||||||
}
|
// }
|
||||||
} catch (JSONException e) {
|
// }
|
||||||
Log.d("MP3Downloader", e + "");
|
// });
|
||||||
}
|
// }
|
||||||
}
|
//
|
||||||
});
|
// @Override
|
||||||
}
|
// public void downloadTrack(String url, File outDir, ru.vtosters.lite.music.Callback callback) {
|
||||||
|
//
|
||||||
@RequiresApi(api = Build.VERSION_CODES.M)
|
// }
|
||||||
private static void downloadMP3(String title, String url) {
|
//}
|
||||||
var downloadManager = AndroidUtils.getGlobalContext().getSystemService(DownloadManager.class);
|
|
||||||
var request = new DownloadManager.Request(Uri.parse(url))
|
|
||||||
.setAllowedOverRoaming(true)
|
|
||||||
.setTitle("Downloading " + title)
|
|
||||||
.setDestinationInExternalFilesDir(AndroidUtils.getGlobalContext(),
|
|
||||||
Environment.DIRECTORY_MUSIC,
|
|
||||||
title + ".mp3")
|
|
||||||
.setVisibleInDownloadsUi(true);
|
|
||||||
downloadManager.enqueue(request);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import static ru.vtosters.lite.utils.AndroidUtils.edit;
|
|||||||
import static ru.vtosters.lite.utils.AndroidUtils.getDefaultPrefs;
|
import static ru.vtosters.lite.utils.AndroidUtils.getDefaultPrefs;
|
||||||
import static ru.vtosters.lite.utils.AndroidUtils.getPreferences;
|
import static ru.vtosters.lite.utils.AndroidUtils.getPreferences;
|
||||||
import static ru.vtosters.lite.utils.AndroidUtils.sendToast;
|
import static ru.vtosters.lite.utils.AndroidUtils.sendToast;
|
||||||
|
import static ru.vtosters.lite.utils.Preferences.autocache;
|
||||||
|
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
@@ -19,6 +20,7 @@ import java.util.ArrayList;
|
|||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.TreeMap;
|
import java.util.TreeMap;
|
||||||
|
|
||||||
|
import ru.vtosters.lite.downloaders.AudioDownloader;
|
||||||
import ru.vtosters.lite.net.NetCall;
|
import ru.vtosters.lite.net.NetCall;
|
||||||
import ru.vtosters.lite.net.NetCallback;
|
import ru.vtosters.lite.net.NetCallback;
|
||||||
import ru.vtosters.lite.net.NetClient;
|
import ru.vtosters.lite.net.NetClient;
|
||||||
@@ -86,6 +88,8 @@ public class Scrobbler {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (autocache()) AudioDownloader.cacheTrack(musictrack);
|
||||||
|
|
||||||
scrobbleTrack(duration, artist, title, uid);
|
scrobbleTrack(duration, artist, title, uid);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -120,7 +124,7 @@ public class Scrobbler {
|
|||||||
@Override
|
@Override
|
||||||
public void onFailure(NetCall call, IOException e) {
|
public void onFailure(NetCall call, IOException e) {
|
||||||
Log.d("Scrobbler", "Auth failed", e);
|
Log.d("Scrobbler", "Auth failed", e);
|
||||||
sendToast(AndroidUtils.getString("lastfm_auth_error"));
|
sendToast(AndroidUtils.getString("auth_error_vtl"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -18,6 +18,10 @@ public class VKM3UParser {
|
|||||||
init();
|
init();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static boolean isM3U8(String str) {
|
||||||
|
return str.endsWith(".ts") || str.endsWith(".tp") || str.endsWith(".mpeg-ts") || str.endsWith(".m2ts");
|
||||||
|
}
|
||||||
|
|
||||||
private void init() {
|
private void init() {
|
||||||
int i = 0;
|
int i = 0;
|
||||||
Scanner scanner = new Scanner(mData);
|
Scanner scanner = new Scanner(mData);
|
||||||
@@ -51,10 +55,6 @@ public class VKM3UParser {
|
|||||||
return directive.substring(directive.indexOf(":") + 1);
|
return directive.substring(directive.indexOf(":") + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean isM3U8(String str) {
|
|
||||||
return str.endsWith(".ts") || str.endsWith(".tp") || str.endsWith(".mpeg-ts") || str.endsWith(".m2ts");
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getHeapSize() {
|
public int getHeapSize() {
|
||||||
return mHeapSize;
|
return mHeapSize;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,346 @@
|
|||||||
|
package ru.vtosters.lite.music.cache;
|
||||||
|
|
||||||
|
import static ru.vtosters.lite.music.cache.FileCacheImplementation.getCacheDir;
|
||||||
|
import static ru.vtosters.lite.utils.AndroidUtils.getGlobalContext;
|
||||||
|
import static ru.vtosters.lite.utils.AndroidUtils.getString;
|
||||||
|
import static ru.vtosters.lite.utils.AndroidUtils.sendToast;
|
||||||
|
import static ru.vtosters.lite.utils.IOUtils.deleteRecursive;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.database.Cursor;
|
||||||
|
import android.database.DatabaseUtils;
|
||||||
|
import android.database.SQLException;
|
||||||
|
import android.database.sqlite.SQLiteDatabase;
|
||||||
|
import android.database.sqlite.SQLiteOpenHelper;
|
||||||
|
import android.os.RemoteException;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.annotation.Nullable;
|
||||||
|
|
||||||
|
import com.vk.core.util.ToastUtils;
|
||||||
|
import com.vk.dto.music.MusicTrack;
|
||||||
|
|
||||||
|
import org.json.JSONObject;
|
||||||
|
|
||||||
|
import java.net.URLDecoder;
|
||||||
|
import java.net.URLEncoder;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import bruhcollective.itaysonlab.libvkx.ILibVkxService;
|
||||||
|
import bruhcollective.itaysonlab.libvkx.client.LibVKXClient;
|
||||||
|
import bruhcollective.itaysonlab.libvkx.client.LibVKXClientImpl;
|
||||||
|
|
||||||
|
public class CacheDatabaseDelegate {
|
||||||
|
private static final int DB_VERSION = 0x1;
|
||||||
|
private static final String DB_NAME = "vt_lite_cache.db";
|
||||||
|
private static final String TABLE_NAME = "tracks";
|
||||||
|
private static final String COLUMN_ID = "id";
|
||||||
|
private static final String COLUMN_TRACK_ID = "trackId";
|
||||||
|
private static final String COLUMN_ALBUM_ID = "albumId";
|
||||||
|
private static final String COLUMN_TITLE = "title";
|
||||||
|
private static final String COLUMN_SUBTITLE = "subtitle";
|
||||||
|
private static final String COLUMN_ARTIST = "artist";
|
||||||
|
private static final String COLUMN_ALBUM_TITLE = "albumTitle";
|
||||||
|
private static final String COLUMN_EXPLICIT = "explicit";
|
||||||
|
private static final String COLUMN_HAS_ARTWORK = "hasArtwork";
|
||||||
|
private static final String COLUMN_DURATION = "duration";
|
||||||
|
private static DbHelper helperInstance;
|
||||||
|
|
||||||
|
protected static DbHelper getHelper() {
|
||||||
|
if (helperInstance == null) helperInstance = new DbHelper(getGlobalContext());
|
||||||
|
return helperInstance;
|
||||||
|
}
|
||||||
|
|
||||||
|
// You MUST call this method ONLY AFTER TRACK IS DOWNLOADED!
|
||||||
|
public static void insertTrack(MusicTrack track) {
|
||||||
|
try {
|
||||||
|
var json = track.J();
|
||||||
|
var albumNode = json.optJSONObject("album");
|
||||||
|
|
||||||
|
var hasArtwork = false;
|
||||||
|
var albumId = -1;
|
||||||
|
var albumName = "";
|
||||||
|
|
||||||
|
if (albumNode != null) {
|
||||||
|
hasArtwork = albumNode.has("thumb");
|
||||||
|
albumId = albumNode.getInt("id");
|
||||||
|
albumName = albumNode.getString("title");
|
||||||
|
}
|
||||||
|
|
||||||
|
var formula = String.format(
|
||||||
|
"INSERT INTO %s (%s, %s, %s, %s, %s, %s, %s, %s, %s) VALUES ('%s', %s, '%s', '%s', '%s', '%s', %s, %s, %s)",
|
||||||
|
TABLE_NAME,
|
||||||
|
COLUMN_TRACK_ID, COLUMN_ALBUM_ID, COLUMN_TITLE, COLUMN_SUBTITLE, COLUMN_ARTIST, COLUMN_ALBUM_TITLE, COLUMN_EXPLICIT, COLUMN_DURATION, COLUMN_HAS_ARTWORK,
|
||||||
|
track.y1(),
|
||||||
|
albumId,
|
||||||
|
URLEncoder.encode(json.getString("title"), "UTF-8"),
|
||||||
|
URLEncoder.encode(json.optString("subtitle"), "UTF-8"),
|
||||||
|
URLEncoder.encode(json.getString("artist"), "UTF-8"),
|
||||||
|
URLEncoder.encode(albumName, "UTF-8"),
|
||||||
|
json.optInt("is_explicit"),
|
||||||
|
json.getInt("duration"),
|
||||||
|
hasArtwork ? 1 : 0
|
||||||
|
);
|
||||||
|
getHelper().getReadableDatabase().execSQL(formula);
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
ToastUtils.a(getString("track_bd_insert_err") + " [" + e.getMessage() + "]", true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void insertTracks(List<MusicTrack> tracks) {
|
||||||
|
for (var track : tracks) insertTrack(track);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void clear() {
|
||||||
|
getHelper().getReadableDatabase().execSQL(String.format("DELETE FROM %s", TABLE_NAME));
|
||||||
|
deleteRecursive(getCacheDir());
|
||||||
|
sendToast(getString("cached_tracks_deleted"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
private static JSONObject reconstructFromDb(Cursor cursor) {
|
||||||
|
try {
|
||||||
|
var trackId = cursor.getString(getColumnIndex(cursor, COLUMN_TRACK_ID));
|
||||||
|
var splits = trackId.split("_");
|
||||||
|
var id = Integer.parseInt(splits[1]);
|
||||||
|
var ownerId = Integer.parseInt(splits[0]);
|
||||||
|
|
||||||
|
return new JSONObject()
|
||||||
|
.put("url", FileCacheImplementation.getServerPath())
|
||||||
|
.put("id", id)
|
||||||
|
.put("owner_id", ownerId)
|
||||||
|
.put("title", URLDecoder.decode(cursor.getString(getColumnIndex(cursor, COLUMN_TITLE)), "UTF-8"))
|
||||||
|
.put("subtitle", URLDecoder.decode(cursor.getString(getColumnIndex(cursor, COLUMN_SUBTITLE)), "UTF-8"))
|
||||||
|
.put("artist", URLDecoder.decode(cursor.getString(getColumnIndex(cursor, COLUMN_ARTIST)), "UTF-8"))
|
||||||
|
.put("duration", cursor.getInt(getColumnIndex(cursor, COLUMN_DURATION)))
|
||||||
|
.put("is_explicit", cursor.getInt(getColumnIndex(cursor, COLUMN_EXPLICIT)))
|
||||||
|
.put("access_key", 2281488)
|
||||||
|
.putOpt("album", reconstructAlbumFromDb(cursor, trackId));
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
return new JSONObject();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
private static JSONObject reconstructAlbumFromDb(Cursor cursor, String trackId) {
|
||||||
|
try {
|
||||||
|
if (!FileCacheImplementation.getTrackThumbnail(trackId, 300).exists()
|
||||||
|
&& !FileCacheImplementation.getTrackThumbnail(trackId, 600).exists()
|
||||||
|
&& !FileCacheImplementation.getTrackThumbnail(trackId, 1200).exists()
|
||||||
|
) {
|
||||||
|
var ownerId = Integer.parseInt(trackId.split("_")[1]);
|
||||||
|
return new JSONObject()
|
||||||
|
.put("id", cursor.getInt(getColumnIndex(cursor, COLUMN_ALBUM_ID)))
|
||||||
|
.put("owner_id", ownerId)
|
||||||
|
.put("title", URLDecoder.decode(cursor.getString(getColumnIndex(cursor, COLUMN_ALBUM_TITLE)), "UTF-8"))
|
||||||
|
.putOpt("thumb", reconstructAlbumThumbFromDb(cursor, trackId));
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
private static JSONObject reconstructAlbumThumbFromDb(Cursor cursor, String trackId) {
|
||||||
|
try {
|
||||||
|
if (cursor.getInt(getColumnIndex(cursor, COLUMN_HAS_ARTWORK)) != 0)
|
||||||
|
new JSONObject()
|
||||||
|
.put("height", 600)
|
||||||
|
.put("width", 600)
|
||||||
|
.putOpt("photo_300", FileCacheImplementation.getFileUri(FileCacheImplementation.getTrackThumbnail(trackId, 300)))
|
||||||
|
.putOpt("photo_600", FileCacheImplementation.getFileUri(FileCacheImplementation.getTrackThumbnail(trackId, 600)))
|
||||||
|
.putOpt("photo_1200", FileCacheImplementation.getFileUri(FileCacheImplementation.getTrackThumbnail(trackId, 1200)));
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int getColumnIndex(Cursor cursor, String name) {
|
||||||
|
return cursor.getColumnIndexOrThrow(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean hasTracks() {
|
||||||
|
if (LibVKXClient.isIntegrationEnabled()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
var formula = String.format(
|
||||||
|
"SELECT COUNT(%s) FROM %s",
|
||||||
|
COLUMN_ID,
|
||||||
|
TABLE_NAME
|
||||||
|
);
|
||||||
|
var cursor = getHelper().getReadableDatabase().rawQuery(formula, null);
|
||||||
|
if (cursor != null) {
|
||||||
|
cursor.moveToFirst();
|
||||||
|
int count = cursor.getInt(0);
|
||||||
|
cursor.close();
|
||||||
|
return count > 0;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static List<MusicTrack> getTracks() {
|
||||||
|
return getTracks(String.format(
|
||||||
|
"SELECT * FROM %s",
|
||||||
|
TABLE_NAME
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static List<MusicTrack> getTracksAsPlaylist() {
|
||||||
|
return getTracks(String.format(
|
||||||
|
"SELECT * FROM %s WHERE %s > -1 GROUP BY %s HAVING COUNT(*) > 1 ORDER by id DESC",
|
||||||
|
TABLE_NAME,
|
||||||
|
COLUMN_ALBUM_ID,
|
||||||
|
COLUMN_ALBUM_ID
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static List<MusicTrack> getTracksByAlbum(String id) {
|
||||||
|
return getTracks(String.format(
|
||||||
|
"SELECT COUNT(%s) FROM %s WHERE %s = %s",
|
||||||
|
COLUMN_ID,
|
||||||
|
TABLE_NAME,
|
||||||
|
COLUMN_ALBUM_ID,
|
||||||
|
id
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static List<MusicTrack> getTracksByAlbumOne(String id) {
|
||||||
|
return getTracks(String.format(
|
||||||
|
"SELECT * FROM %s WHERE %s = %s LIMIT 1",
|
||||||
|
TABLE_NAME,
|
||||||
|
COLUMN_ALBUM_ID,
|
||||||
|
id
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static List<MusicTrack> getTracks(String query) {
|
||||||
|
List<MusicTrack> list = new ArrayList<>();
|
||||||
|
try (Cursor cursor = getHelper().getReadableDatabase().rawQuery(query, new String[0])) {
|
||||||
|
while (cursor.moveToNext()) {
|
||||||
|
list.add(new MusicTrack(reconstructFromDb(cursor)));
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean isCached(String trackId) {
|
||||||
|
var formula = String.format(
|
||||||
|
"SELECT COUNT(%s) FROM %s WHERE %s = '%s'",
|
||||||
|
COLUMN_ID,
|
||||||
|
TABLE_NAME,
|
||||||
|
COLUMN_TRACK_ID,
|
||||||
|
trackId
|
||||||
|
);
|
||||||
|
try {
|
||||||
|
Cursor size = getHelper().getReadableDatabase().rawQuery(formula, null);
|
||||||
|
if (size != null) {
|
||||||
|
size.moveToFirst();
|
||||||
|
int count = size.getInt(0);
|
||||||
|
size.close();
|
||||||
|
return count != 0;
|
||||||
|
}
|
||||||
|
} catch (SQLException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean isVkxCached(int playlist_id, int owner_id) {
|
||||||
|
return LibVKXClient.getInstance().runOnServiceSync(new LibVKXClientImpl.LibVKXActionGeneric<>() {
|
||||||
|
@Override
|
||||||
|
public Boolean run(ILibVkxService service) {
|
||||||
|
try {
|
||||||
|
return service.isPlaylistCached(playlist_id, owner_id);
|
||||||
|
} catch (RemoteException e) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Boolean defaultValue() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean isVkxCached(String trackId) {
|
||||||
|
return LibVKXClient.getInstance().runOnServiceSync(new LibVKXClientImpl.LibVKXActionGeneric<>() {
|
||||||
|
@Override
|
||||||
|
public Boolean run(ILibVkxService service) {
|
||||||
|
try {
|
||||||
|
var splits = trackId.split("_");
|
||||||
|
var id = Integer.parseInt(splits[1]);
|
||||||
|
var owner = Integer.parseInt(splits[0]);
|
||||||
|
return service.isTrackCached(id, owner);
|
||||||
|
} catch (RemoteException e) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Boolean defaultValue() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void removeTrackFromCache(String trackId) {
|
||||||
|
deleteRecursive(FileCacheImplementation.getTrackFolder(trackId));
|
||||||
|
|
||||||
|
var formula = String.format(
|
||||||
|
"DELETE FROM %s WHERE %s = '%s'",
|
||||||
|
TABLE_NAME,
|
||||||
|
COLUMN_TRACK_ID,
|
||||||
|
trackId
|
||||||
|
);
|
||||||
|
getHelper().getWritableDatabase().execSQL(formula);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static long getTrackCount() {
|
||||||
|
if (!LibVKXClient.isIntegrationEnabled())
|
||||||
|
return DatabaseUtils.queryNumEntries(getHelper().getReadableDatabase(), TABLE_NAME);
|
||||||
|
return LibVKXClient.getInstance().runOnServiceSync(new LibVKXClientImpl.LibVKXActionGeneric<Long>() {
|
||||||
|
@Override
|
||||||
|
public Long run(ILibVkxService service) {
|
||||||
|
try {
|
||||||
|
return (long) service.getCache().size();
|
||||||
|
} catch (RemoteException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
return defaultValue();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Long defaultValue() {
|
||||||
|
return 0L;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class DbHelper extends SQLiteOpenHelper {
|
||||||
|
public DbHelper(Context context) {
|
||||||
|
super(context, DB_NAME, null, DB_VERSION);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void onCreate(SQLiteDatabase db) {
|
||||||
|
var formula = String.format(
|
||||||
|
"CREATE TABLE %s (%s INTEGER PRIMARY KEY AUTOINCREMENT, %s TEXT, %s INTEGER, %s TEXT, %s TEXT, %s TEXT, %s TEXT, %s INTEGER, %s INTEGER, %s INTEGER)",
|
||||||
|
TABLE_NAME,
|
||||||
|
COLUMN_ID, COLUMN_TRACK_ID, COLUMN_ALBUM_ID, COLUMN_TITLE, COLUMN_SUBTITLE, COLUMN_ARTIST, COLUMN_ALBUM_TITLE, COLUMN_EXPLICIT, COLUMN_DURATION, COLUMN_HAS_ARTWORK
|
||||||
|
);
|
||||||
|
db.execSQL(formula);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,60 @@
|
|||||||
|
package ru.vtosters.lite.music.cache;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.net.Uri;
|
||||||
|
|
||||||
|
import com.vk.dto.music.MusicTrack;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
|
||||||
|
import ru.vtosters.lite.utils.AndroidUtils;
|
||||||
|
import ru.vtosters.lite.utils.IOUtils;
|
||||||
|
|
||||||
|
public class FileCacheImplementation {
|
||||||
|
|
||||||
|
public static void clear() {
|
||||||
|
CacheDatabaseDelegate.clear();
|
||||||
|
IOUtils.deleteRecursive(getCacheDir(), false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static File getCacheDir() {
|
||||||
|
return AndroidUtils.getGlobalContext().getDir("vt_tracks", Context.MODE_PRIVATE);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static File getTrackFolder(String trackId) {
|
||||||
|
var dir = new File(getCacheDir(), trackId);
|
||||||
|
dir.mkdirs();
|
||||||
|
return dir;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static File getThumbnailsFolder(String trackId) {
|
||||||
|
var dir = new File(getTrackFolder(trackId), "thumbs");
|
||||||
|
dir.mkdirs();
|
||||||
|
return dir;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static File getTrackFile(String trackId) {
|
||||||
|
return new File(getTrackFolder(trackId), "track.mp3");
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean isTrackExist(String trackId) {
|
||||||
|
return CacheDatabaseDelegate.isCached(trackId);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static File getTrackFile(MusicTrack track) {
|
||||||
|
return getTrackFile(track.y1());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static File getTrackThumbnail(String trackId, int factor) {
|
||||||
|
return new File(getThumbnailsFolder(trackId), "thumb_" + factor + ".png");
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String getFileUri(File file) {
|
||||||
|
if (!file.exists()) return null;
|
||||||
|
return Uri.fromFile(file).toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String getServerPath() {
|
||||||
|
return "https://vtosters.app";
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,93 @@
|
|||||||
|
package ru.vtosters.lite.music.cache.helpers;
|
||||||
|
|
||||||
|
import static ru.vtosters.lite.utils.AndroidUtils.getString;
|
||||||
|
|
||||||
|
import com.vk.dto.music.Playlist;
|
||||||
|
|
||||||
|
import org.json.JSONArray;
|
||||||
|
import org.json.JSONException;
|
||||||
|
import org.json.JSONObject;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import ru.vtosters.lite.music.cache.CacheDatabaseDelegate;
|
||||||
|
import ru.vtosters.lite.music.cache.FileCacheImplementation;
|
||||||
|
import ru.vtosters.lite.utils.AccountManagerUtils;
|
||||||
|
|
||||||
|
public class PlaylistHelper {
|
||||||
|
|
||||||
|
public static Playlist createCachedPlaylistMetadata() {
|
||||||
|
try {
|
||||||
|
var obj = new JSONObject()
|
||||||
|
.put("id", -1)
|
||||||
|
.put("owner_id", AccountManagerUtils.getUserId())
|
||||||
|
.put("type", 0)
|
||||||
|
.put("album_type", "playlist")
|
||||||
|
.put("title", getString("cached_tracks_title"))
|
||||||
|
.put("description", getString("cached_tracks_desc"))
|
||||||
|
.put("count", 0);
|
||||||
|
return new Playlist(obj);
|
||||||
|
} catch (JSONException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Playlist createCachedPlaylistMetadata(String id) {
|
||||||
|
var track = TracklistHelper.getTracksOne(id).get(0);
|
||||||
|
var albumLink = track.I;
|
||||||
|
var thumb = albumLink.u1();
|
||||||
|
return createAlbum(
|
||||||
|
thumb != null ? thumb.h(600) : "",
|
||||||
|
albumLink.getTitle(),
|
||||||
|
track.C,
|
||||||
|
track.y1(),
|
||||||
|
albumLink.getId()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Playlist createAlbum(String photo, String title, String artist, String trackId, int albumId) {
|
||||||
|
try {
|
||||||
|
var jPhoto = new JSONObject();
|
||||||
|
if (!photo.isEmpty())
|
||||||
|
jPhoto.put("height", 600)
|
||||||
|
.put("width", 600)
|
||||||
|
.putOpt("photo_300", FileCacheImplementation.getFileUri(FileCacheImplementation.getTrackThumbnail(trackId, 300)))
|
||||||
|
.putOpt("photo_600", FileCacheImplementation.getFileUri(FileCacheImplementation.getTrackThumbnail(trackId, 600)));
|
||||||
|
var obj = new JSONObject()
|
||||||
|
.put("id", -2)
|
||||||
|
.put("owner_id", albumId)
|
||||||
|
.put("type", 1)
|
||||||
|
.put("album_type", "main_only")
|
||||||
|
.put("title", title)
|
||||||
|
.put("description", albumId + "/ " + getString("cached_album_warning"))
|
||||||
|
.put("main_artists", new JSONArray()
|
||||||
|
.put(new JSONObject().put("name", artist)
|
||||||
|
.put("id", "-1")
|
||||||
|
.put("domain", "-1")))
|
||||||
|
.putOpt("photo", jPhoto)
|
||||||
|
.put("count", 0);
|
||||||
|
return new Playlist(obj);
|
||||||
|
} catch (JSONException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static List<Playlist> getAlbumPlaylists() {
|
||||||
|
List<Playlist> list = new ArrayList<>();
|
||||||
|
for (var track : CacheDatabaseDelegate.getTracksAsPlaylist()) {
|
||||||
|
var albumLink = track.I;
|
||||||
|
var thumb = albumLink.u1();
|
||||||
|
list.add(createAlbum(
|
||||||
|
thumb != null ? thumb.h(600) : "",
|
||||||
|
albumLink.getTitle(),
|
||||||
|
track.C,
|
||||||
|
track.y1(),
|
||||||
|
albumLink.getId()
|
||||||
|
));
|
||||||
|
}
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,74 @@
|
|||||||
|
package ru.vtosters.lite.music.cache.helpers;
|
||||||
|
|
||||||
|
import android.util.Log;
|
||||||
|
|
||||||
|
import com.vk.dto.music.MusicTrack;
|
||||||
|
|
||||||
|
import org.json.JSONArray;
|
||||||
|
import org.json.JSONException;
|
||||||
|
import org.json.JSONObject;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.net.MalformedURLException;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import bruhcollective.itaysonlab.libvkx.client.LibVKXClient;
|
||||||
|
import ru.vtosters.lite.music.cache.CacheDatabaseDelegate;
|
||||||
|
import ru.vtosters.lite.music.cache.FileCacheImplementation;
|
||||||
|
|
||||||
|
public class TracklistHelper {
|
||||||
|
|
||||||
|
public static List<MusicTrack> getTracks() {
|
||||||
|
return CacheDatabaseDelegate.getTracks();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static List<MusicTrack> getTracks(String id) {
|
||||||
|
return CacheDatabaseDelegate.getTracksByAlbum(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static List<MusicTrack> getTracksOne(String id) {
|
||||||
|
return CacheDatabaseDelegate.getTracksByAlbumOne(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static JSONArray tracksToIds(List<MusicTrack> tracks) {
|
||||||
|
var arr = new JSONArray();
|
||||||
|
for (MusicTrack track : tracks) {
|
||||||
|
arr.put(track.y1());
|
||||||
|
}
|
||||||
|
return arr;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static JSONArray tracksToJsons(List<MusicTrack> tracks) {
|
||||||
|
var arr = new JSONArray();
|
||||||
|
for (MusicTrack track : tracks) {
|
||||||
|
var json = track.J();
|
||||||
|
var folder = FileCacheImplementation.getThumbnailsFolder(LibVKXClient.asId(track));
|
||||||
|
try {
|
||||||
|
addCachedThumbnails(json, folder);
|
||||||
|
} catch (JSONException | MalformedURLException e) {
|
||||||
|
Log.d("TracklistHelper", e.getMessage());
|
||||||
|
}
|
||||||
|
arr.put(json);
|
||||||
|
}
|
||||||
|
return arr;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void addCachedThumbnails(JSONObject target, File thumbnailsDir)
|
||||||
|
throws JSONException, MalformedURLException {
|
||||||
|
var sizes = new JSONArray();
|
||||||
|
var files = thumbnailsDir.listFiles();
|
||||||
|
if (files == null || files.length == 0)
|
||||||
|
return;
|
||||||
|
for (var file : files) {
|
||||||
|
var filename = file.getName();
|
||||||
|
var width = Integer.parseInt(filename.substring(6, filename.length() - 4));
|
||||||
|
var src = file.toURI().toURL().toString();
|
||||||
|
Log.d("tracksToJsons", src);
|
||||||
|
var size = new JSONObject()
|
||||||
|
.put("width", width)
|
||||||
|
.put("src", src);
|
||||||
|
sizes.put(size);
|
||||||
|
}
|
||||||
|
target.put("album", new JSONObject().put("thumb", new JSONObject().put("sizes", sizes)));
|
||||||
|
}
|
||||||
|
}
|
||||||
+106
@@ -0,0 +1,106 @@
|
|||||||
|
package ru.vtosters.lite.music.cache.injectors;
|
||||||
|
|
||||||
|
import android.os.RemoteException;
|
||||||
|
import android.text.TextUtils;
|
||||||
|
import android.util.Log;
|
||||||
|
|
||||||
|
import com.vk.api.audio.AudioGetPlaylist;
|
||||||
|
import com.vk.dto.music.MusicTrack;
|
||||||
|
import com.vk.dto.music.Playlist;
|
||||||
|
|
||||||
|
import org.json.JSONException;
|
||||||
|
import org.json.JSONObject;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import bruhcollective.itaysonlab.libvkx.client.LibVKXClient;
|
||||||
|
import io.reactivex.Observable;
|
||||||
|
import io.reactivex.ObservableOnSubscribe;
|
||||||
|
import ru.vtosters.lite.downloaders.AudioDownloader;
|
||||||
|
import ru.vtosters.lite.music.cache.CacheDatabaseDelegate;
|
||||||
|
import ru.vtosters.lite.music.cache.helpers.PlaylistHelper;
|
||||||
|
import ru.vtosters.lite.music.cache.helpers.TracklistHelper;
|
||||||
|
import ru.vtosters.lite.utils.NetworkUtils;
|
||||||
|
|
||||||
|
public class PlaylistInjector {
|
||||||
|
|
||||||
|
public final static String CHANNEL_NAME = "VTCH";
|
||||||
|
|
||||||
|
public static void injectDownloadPlaylist(Playlist playlist) {
|
||||||
|
AudioDownloader.cachePlaylist(playlist);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean eligibleForOfflineCaching() {
|
||||||
|
Log.d("PlaylistInjector", "eligibleForOfflineCaching");
|
||||||
|
|
||||||
|
return !NetworkUtils.isNetworkConnected() && CacheDatabaseDelegate.hasTracks();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Observable<AudioGetPlaylist.c> injectGetPlaylist(AudioGetPlaylist audioGetPlaylist) {
|
||||||
|
Log.d("PlaylistInjector", "injectGetPlaylist");
|
||||||
|
|
||||||
|
try {
|
||||||
|
if (!eligibleForOfflineCaching())
|
||||||
|
return null;
|
||||||
|
var requestArgs = audioGetPlaylist.b();
|
||||||
|
|
||||||
|
var id = requestArgs.get("id");
|
||||||
|
var ownerId = requestArgs.get("owner_id");
|
||||||
|
var accessKey = requestArgs.get("access_key");
|
||||||
|
boolean isVirtualPlaylist = accessKey != null && (accessKey.equals("cache"));
|
||||||
|
boolean isAlbumVirtualPlaylist = accessKey != null && (accessKey.equals("cacheAlbum"));
|
||||||
|
|
||||||
|
Log.d("PlaylistInjector", "id = " + id + " / owner = " + ownerId + " / access = " + accessKey + " / " + isVirtualPlaylist + " + " + isAlbumVirtualPlaylist);
|
||||||
|
|
||||||
|
if (TextUtils.isEmpty(id) || (!isVirtualPlaylist && !isAlbumVirtualPlaylist))
|
||||||
|
return null;
|
||||||
|
|
||||||
|
return Observable.a((ObservableOnSubscribe<AudioGetPlaylist.c>) observableEmitter -> {
|
||||||
|
AudioGetPlaylist.c response = new AudioGetPlaylist.c();
|
||||||
|
|
||||||
|
if (LibVKXClient.isIntegrationEnabled()) {
|
||||||
|
LibVKXClient.getInstance().runOnService((service) -> {
|
||||||
|
try {
|
||||||
|
List<String> cache;
|
||||||
|
ArrayList<MusicTrack> tracks = new ArrayList<>();
|
||||||
|
|
||||||
|
if (isAlbumVirtualPlaylist) {
|
||||||
|
response.b = new Playlist(new JSONObject(service.getPlaylistDefJson(id, ownerId)));
|
||||||
|
cache = service.getTracksInPlaylist(id, ownerId);
|
||||||
|
} else {
|
||||||
|
response.b = PlaylistHelper.createCachedPlaylistMetadata();
|
||||||
|
cache = service.getCache();
|
||||||
|
}
|
||||||
|
|
||||||
|
for (String json : cache) {
|
||||||
|
tracks.add(new MusicTrack(new JSONObject(json)));
|
||||||
|
}
|
||||||
|
|
||||||
|
response.c = tracks;
|
||||||
|
} catch (RemoteException | JSONException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
response.c = new ArrayList<>();
|
||||||
|
}
|
||||||
|
observableEmitter.b(response);
|
||||||
|
});
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isVirtualPlaylist) {
|
||||||
|
response.c = (ArrayList<MusicTrack>) TracklistHelper.getTracks();
|
||||||
|
response.b = PlaylistHelper.createCachedPlaylistMetadata();
|
||||||
|
} else {
|
||||||
|
response.c = (ArrayList<MusicTrack>) TracklistHelper.getTracks(requestArgs.get("owner_id"));
|
||||||
|
response.b = PlaylistHelper.createCachedPlaylistMetadata(requestArgs.get("owner_id"));
|
||||||
|
}
|
||||||
|
|
||||||
|
observableEmitter.b(response);
|
||||||
|
});
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
+223
@@ -0,0 +1,223 @@
|
|||||||
|
package ru.vtosters.lite.music.cache.injectors;
|
||||||
|
|
||||||
|
import static ru.vtosters.lite.music.cache.CacheDatabaseDelegate.hasTracks;
|
||||||
|
import static ru.vtosters.lite.utils.AndroidUtils.getString;
|
||||||
|
|
||||||
|
import android.util.Log;
|
||||||
|
|
||||||
|
import com.vk.catalog2.core.CatalogParser;
|
||||||
|
import com.vk.catalog2.core.api.dto.CatalogResponse;
|
||||||
|
import com.vk.dto.music.MusicTrack;
|
||||||
|
|
||||||
|
import org.json.JSONArray;
|
||||||
|
import org.json.JSONException;
|
||||||
|
import org.json.JSONObject;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
import bruhcollective.itaysonlab.libvkx.client.LibVKXClient;
|
||||||
|
import io.reactivex.Observable;
|
||||||
|
import io.reactivex.ObservableOnSubscribe;
|
||||||
|
import ru.vtosters.lite.music.cache.helpers.PlaylistHelper;
|
||||||
|
import ru.vtosters.lite.music.cache.helpers.TracklistHelper;
|
||||||
|
import ru.vtosters.lite.utils.AccountManagerUtils;
|
||||||
|
import ru.vtosters.lite.utils.NetworkUtils;
|
||||||
|
|
||||||
|
public class TracklistInjector {
|
||||||
|
|
||||||
|
public static boolean eligibleForOfflineCaching() {
|
||||||
|
return !NetworkUtils.isNetworkConnected();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Observable<CatalogResponse> createOfflineRx(CatalogParser parser) {
|
||||||
|
Log.d("TracklistInjector", "createOfflineRx");
|
||||||
|
|
||||||
|
return Observable.a((ObservableOnSubscribe<CatalogResponse>) observableEmitter -> {
|
||||||
|
if (LibVKXClient.isIntegrationEnabled()) {
|
||||||
|
LibVKXClient.getInstance().runOnService((service) -> {
|
||||||
|
try {
|
||||||
|
try {
|
||||||
|
Log.d("TracklistInjector", "Using vkx cache catalog");
|
||||||
|
observableEmitter.b(parser.c(new JSONObject(service.getCacheCatalog())));
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
List<MusicTrack> tracks = new ArrayList<>();
|
||||||
|
List<String> cache = service.getCache();
|
||||||
|
|
||||||
|
for (String json : cache) {
|
||||||
|
Log.d("TracklistInjector", "added " + json);
|
||||||
|
tracks.add(new MusicTrack(new JSONObject(json)));
|
||||||
|
}
|
||||||
|
|
||||||
|
Log.d("TracklistInjector", "Using own cache catalog from vkx");
|
||||||
|
observableEmitter.b(parser.c(createVirtualCatalog(tracks)));
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
if (!hasTracks()) {
|
||||||
|
observableEmitter.b(parser.c(getEmptyCatalog()));
|
||||||
|
} else {
|
||||||
|
observableEmitter.b(parser.c(createVirtualCatalog(TracklistHelper.getTracks())));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private static JSONObject getEmptyCatalog() throws JSONException {
|
||||||
|
return new JSONObject("{\"catalog\":{\"default_section\":\"cache\",\"sections\":[{\"id\":\"cache\",\"title\":\"" + getString("cached_content_title") + "\",\"blocks\":[{\"data_type\":\"placeholder\",\"id\":\"0\",\"layout\":{\"name\":\"placeholder_big\"},\"placeholder_ids\":[\"_synth_trackEmpty\"]}]}]},\"audios\":[],\"playlists\":[],\"placeholders\":[{\"id\":\"_synth_trackEmpty\",\"title\":\"" + getString("cached_content_empty") + "\",\"text\":\"" + getString("cached_content_empty_desc") + "\",\"buttons\":[]}]}");
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void injectIntoExistingCatalog(JSONObject catalogNode) {
|
||||||
|
Log.d("TracklistInjector", "injectIntoExistingCatalog");
|
||||||
|
|
||||||
|
if (!hasTracks()) return;
|
||||||
|
try {
|
||||||
|
var sectionsNode = catalogNode.getJSONObject("catalog")
|
||||||
|
.getJSONArray("sections");
|
||||||
|
var firstSection = sectionsNode.getJSONObject(0);
|
||||||
|
if (!firstSection.getString("url").equals("https://vk.com/audios" + AccountManagerUtils.getUserId() + "?section=all"))
|
||||||
|
return;
|
||||||
|
|
||||||
|
var foundPlaylistBlock = false;
|
||||||
|
var suitableIndex = 0;
|
||||||
|
|
||||||
|
var blocks = firstSection.getJSONArray("blocks");
|
||||||
|
for (int i = 0; i < blocks.length(); i++) {
|
||||||
|
var block = blocks.getJSONObject(i);
|
||||||
|
var dataType = block.getString("data_type");
|
||||||
|
if ("music_audios".equals(dataType)) {
|
||||||
|
suitableIndex = i - 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!"music_playlists".equals(dataType))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
var playlistIds = block.getJSONArray("playlists_ids");
|
||||||
|
var newPlaylistIds = new JSONArray()
|
||||||
|
.put(AccountManagerUtils.getUserId() + "_-1");
|
||||||
|
|
||||||
|
for (int j = 0; j < playlistIds.length(); j++)
|
||||||
|
newPlaylistIds.put(playlistIds.get(j));
|
||||||
|
|
||||||
|
block.put("playlists_ids", newPlaylistIds);
|
||||||
|
|
||||||
|
// need test
|
||||||
|
blocks.remove(i);
|
||||||
|
blocks.put(i, block);
|
||||||
|
|
||||||
|
foundPlaylistBlock = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (foundPlaylistBlock) {
|
||||||
|
var playlists = catalogNode.getJSONArray("playlists")
|
||||||
|
.put(0, PlaylistHelper.createCachedPlaylistMetadata().J());
|
||||||
|
catalogNode.put("playlists", playlists);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var ids = new JSONArray()
|
||||||
|
.put(0, AccountManagerUtils.getUserId() + "_-1");
|
||||||
|
|
||||||
|
var playlistsBlock = new JSONObject()
|
||||||
|
.put("id", getRandomId())
|
||||||
|
.put("data_type", "music_playlists")
|
||||||
|
.put("url", "synth:cache:playlists")
|
||||||
|
.put("playlists_ids", ids);
|
||||||
|
|
||||||
|
var layout = new JSONObject()
|
||||||
|
.put("name", "large_slider")
|
||||||
|
.put("owner_id", AccountManagerUtils.getUserId());
|
||||||
|
|
||||||
|
playlistsBlock.put("layout", layout);
|
||||||
|
|
||||||
|
blocks.put(suitableIndex, playlistsBlock);
|
||||||
|
|
||||||
|
firstSection.put("blocks", blocks);
|
||||||
|
|
||||||
|
var playlists = new JSONArray()
|
||||||
|
.put(0, PlaylistHelper.createCachedPlaylistMetadata().J());
|
||||||
|
catalogNode.put("playlists", playlists);
|
||||||
|
} catch (JSONException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static JSONObject createVirtualCatalog(List<MusicTrack> tracks)
|
||||||
|
throws JSONException {
|
||||||
|
Log.d("TracklistInjector", "createVirtualCatalog");
|
||||||
|
|
||||||
|
var clickAction = new JSONObject()
|
||||||
|
.put("type", "open_url")
|
||||||
|
.put("target", "internal")
|
||||||
|
.put("url", "https://vkx.app/index.html?app=vt_ctg");
|
||||||
|
|
||||||
|
var catalogBanner = new JSONObject()
|
||||||
|
.put("id", 1234)
|
||||||
|
.put("image_mode", "cover")
|
||||||
|
.put("title", getString("vkx_integration_title"))
|
||||||
|
.put("text", getString("vkx_integration_desc"))
|
||||||
|
.put("click_action", new JSONObject().put("action", clickAction));
|
||||||
|
var catalogBanners = new JSONArray()
|
||||||
|
.put(catalogBanner);
|
||||||
|
|
||||||
|
var audiosBlock = new JSONObject()
|
||||||
|
.put("id", getRandomId())
|
||||||
|
.put("data_type", "music_audios")
|
||||||
|
.put("url", "synth:cache:list")
|
||||||
|
.put("audios_ids", TracklistHelper.tracksToIds(tracks));
|
||||||
|
|
||||||
|
var layout = new JSONObject()
|
||||||
|
.put("name", "list")
|
||||||
|
.put("owner_id", AccountManagerUtils.getUserId());
|
||||||
|
|
||||||
|
audiosBlock.put("layout", layout);
|
||||||
|
|
||||||
|
var blocks = new JSONArray()
|
||||||
|
.put(audiosBlock);
|
||||||
|
|
||||||
|
// var vkxPostirony = new JSONObject()
|
||||||
|
// .put("id", getRandomId())
|
||||||
|
// .put("data_type", "catalog_banners")
|
||||||
|
// .put("url", "synth:cache:vkx")
|
||||||
|
// .put("catalog_banner_ids", new JSONArray().put(1234));
|
||||||
|
//
|
||||||
|
// var vkxlayout = new JSONObject()
|
||||||
|
// .put("name", "large_list")
|
||||||
|
// .put("owner_id", Globals.getUserId())
|
||||||
|
// .put("infinite_repeat", true);
|
||||||
|
//
|
||||||
|
// vkxPostirony.put("layout", vkxlayout);
|
||||||
|
//
|
||||||
|
// if (eligibleForVkxAd())
|
||||||
|
// blocks.put(vkxPostirony);
|
||||||
|
var randomId = getRandomId();
|
||||||
|
|
||||||
|
var section = new JSONObject()
|
||||||
|
.put("id", randomId)
|
||||||
|
.put("title", getString("saved_tracks_title"))
|
||||||
|
.put("url", "synth:cache")
|
||||||
|
.put("blocks", blocks);
|
||||||
|
|
||||||
|
var sections = new JSONArray()
|
||||||
|
.put(section);
|
||||||
|
|
||||||
|
var catalog = new JSONObject()
|
||||||
|
.put("sections", sections)
|
||||||
|
.put("default_section", randomId);
|
||||||
|
|
||||||
|
return new JSONObject()
|
||||||
|
.put("catalog", catalog)
|
||||||
|
.put("audios", TracklistHelper.tracksToJsons(tracks))
|
||||||
|
.put("catalog_banners", catalogBanners);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String getRandomId() {
|
||||||
|
return UUID.randomUUID().toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,94 @@
|
|||||||
|
package ru.vtosters.lite.music.callback;
|
||||||
|
|
||||||
|
import static ru.vtosters.lite.utils.AndroidUtils.getString;
|
||||||
|
|
||||||
|
import android.util.Log;
|
||||||
|
|
||||||
|
import androidx.core.app.NotificationCompat;
|
||||||
|
import androidx.core.app.NotificationManagerCompat;
|
||||||
|
|
||||||
|
import ru.vtosters.lite.downloaders.notifications.NotificationChannels;
|
||||||
|
import ru.vtosters.lite.music.Callback;
|
||||||
|
|
||||||
|
public class MusicCallbackBuilder {
|
||||||
|
private static final NotificationManagerCompat notificationManager = NotificationChannels.getNotificationManager();
|
||||||
|
|
||||||
|
public static Callback buildOneTrackCallback(int notificationId, NotificationCompat.Builder notification) {
|
||||||
|
return new Callback() {
|
||||||
|
long startTime = 0;
|
||||||
|
long elapsedTime = 0;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onProgress(int progress) {
|
||||||
|
if (elapsedTime > 1000) {
|
||||||
|
notification.setProgress(100, progress, false);
|
||||||
|
notificationManager.notify(notificationId, notification.build());
|
||||||
|
|
||||||
|
startTime = System.currentTimeMillis();
|
||||||
|
elapsedTime = 0;
|
||||||
|
} else {
|
||||||
|
elapsedTime = System.currentTimeMillis() - startTime;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onSuccess() {
|
||||||
|
try {
|
||||||
|
notification
|
||||||
|
.setContentText(getString("player_download_finished"))
|
||||||
|
.setProgress(0, 0, false)
|
||||||
|
.setSmallIcon(android.R.drawable.stat_sys_download_done);
|
||||||
|
notificationManager.notify(notificationId, notification.build());
|
||||||
|
} catch (UnsatisfiedLinkError e) {
|
||||||
|
Log.e("AudioDownloader", "native libs");
|
||||||
|
Log.e("AudioDownloader", e.getMessage());
|
||||||
|
onFailure();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onFailure() {
|
||||||
|
notification.setContentText(getString("load_audio_error")).setProgress(0, 0, false);
|
||||||
|
notificationManager.notify(notificationId, notification.build());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onSizeReceived(long size, long header) {
|
||||||
|
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Callback buildPlaylistCallback(int playlistSize, NotificationCompat.Builder notification, int notificationId) {
|
||||||
|
return new Callback() {
|
||||||
|
@Override
|
||||||
|
public void onProgress(int progress) {
|
||||||
|
if (progress == playlistSize) {
|
||||||
|
onSuccess();
|
||||||
|
} else {
|
||||||
|
notification.setContentText(String.format(getString("playlist_download_notf"), progress, playlistSize));
|
||||||
|
notification.setProgress(playlistSize, progress, false);
|
||||||
|
}
|
||||||
|
notificationManager.notify(notificationId, notification.build());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onSuccess() {
|
||||||
|
notification.setContentText(getString("player_download_finished"));
|
||||||
|
notification.setProgress(0, 0, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onFailure() {
|
||||||
|
notification.setContentText(getString("load_audio_error")).setProgress(0, 0, false);
|
||||||
|
notificationManager.notify(notificationId, notification.build());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onSizeReceived(long size, long header) {
|
||||||
|
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,86 @@
|
|||||||
|
package ru.vtosters.lite.music.converter.playlist;
|
||||||
|
|
||||||
|
import static ru.vtosters.lite.hooks.DateHook.getLocale;
|
||||||
|
import static ru.vtosters.lite.proxy.ProxyUtils.getApi;
|
||||||
|
|
||||||
|
import com.vk.core.network.Network;
|
||||||
|
import com.vk.core.util.DeviceIdProvider;
|
||||||
|
import com.vk.dto.music.MusicTrack;
|
||||||
|
import com.vk.dto.music.Playlist;
|
||||||
|
|
||||||
|
import org.json.JSONException;
|
||||||
|
import org.json.JSONObject;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.concurrent.ExecutionException;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
import java8.util.concurrent.CompletableFuture;
|
||||||
|
import okhttp3.Headers;
|
||||||
|
import okhttp3.OkHttpClient;
|
||||||
|
import okhttp3.Request;
|
||||||
|
import ru.vtosters.lite.utils.AccountManagerUtils;
|
||||||
|
import ru.vtosters.lite.utils.AndroidUtils;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* stuff for converting playlists DTO
|
||||||
|
*/
|
||||||
|
public class PlaylistConverter {
|
||||||
|
public static List<MusicTrack> getPlaylist(Playlist oldPlaylist) {
|
||||||
|
var tracks = requestPlaylist(0, oldPlaylist.b, oldPlaylist.Q, oldPlaylist.a);
|
||||||
|
return tracks.stream().filter(track -> !track.D.isEmpty()).collect(Collectors.toList());
|
||||||
|
}
|
||||||
|
|
||||||
|
private static List<MusicTrack> requestPlaylist(int offset, int ownerId, String accessKey, int id) {
|
||||||
|
var audioCount = 1000;
|
||||||
|
var requestUrl = "https://" + getApi() + "/method/execute.getPlaylist" +
|
||||||
|
"?v=5.119" +
|
||||||
|
"&https=1" +
|
||||||
|
"&audio_count=" + audioCount +
|
||||||
|
"&need_playlist=1" +
|
||||||
|
"&device_id=" + DeviceIdProvider.d(AndroidUtils.getGlobalContext()) +
|
||||||
|
"&owner_id=" + ownerId +
|
||||||
|
"&access_key=" + accessKey +
|
||||||
|
"&func_v=5" +
|
||||||
|
"&id=" + id +
|
||||||
|
"&lang=" + getLocale() +
|
||||||
|
"&audio_offset=" + offset +
|
||||||
|
"&need_owner=1" +
|
||||||
|
"&access_token=" + AccountManagerUtils.getUserToken();
|
||||||
|
|
||||||
|
var request = new Request.a()
|
||||||
|
.b(requestUrl)
|
||||||
|
.a(Headers.a("User-Agent", Network.l.c().a(), "Content-Type", "application/x-www-form-urlencoded; charset=utf-8")).a();
|
||||||
|
|
||||||
|
try {
|
||||||
|
var response = CompletableFuture.supplyAsync(() -> {
|
||||||
|
try {
|
||||||
|
return new OkHttpClient().a(request).execute().a().g();
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
).get();
|
||||||
|
var jsonObj = new JSONObject(response);
|
||||||
|
if (!jsonObj.has("response"))
|
||||||
|
return null;
|
||||||
|
var playlist = new JSONObject(response).getJSONObject("response").getJSONArray("audios");
|
||||||
|
var tracks = new ArrayList<MusicTrack>();
|
||||||
|
for (int i = 0; i < playlist.length(); i++) {
|
||||||
|
var track = new MusicTrack(playlist.getJSONObject(i));
|
||||||
|
tracks.add(track);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tracks.size() == audioCount) {
|
||||||
|
tracks.addAll(requestPlaylist(offset + audioCount, ownerId, accessKey, id));
|
||||||
|
}
|
||||||
|
|
||||||
|
return tracks;
|
||||||
|
} catch (JSONException | ExecutionException | InterruptedException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
+59
-37
@@ -1,15 +1,18 @@
|
|||||||
package ru.vtosters.lite.music;
|
package ru.vtosters.lite.music.converter.ts;
|
||||||
|
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
import com.arthenica.ffmpegkit.FFmpegKit;
|
import com.arthenica.ffmpegkit.FFmpegKit;
|
||||||
import com.arthenica.ffmpegkit.ReturnCode;
|
import com.arthenica.ffmpegkit.ReturnCode;
|
||||||
import com.vk.core.util.ToastUtils;
|
import com.vk.core.util.ToastUtils;
|
||||||
|
import com.vk.dto.music.Artist;
|
||||||
|
import com.vk.dto.music.MusicTrack;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileOutputStream;
|
import java.io.FileOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
import ru.vtosters.lite.utils.AndroidUtils;
|
import ru.vtosters.lite.utils.AndroidUtils;
|
||||||
import ru.vtosters.lite.utils.IOUtils;
|
import ru.vtosters.lite.utils.IOUtils;
|
||||||
@@ -17,6 +20,61 @@ import ru.vtosters.lite.utils.IOUtils;
|
|||||||
public class FFMpeg {
|
public class FFMpeg {
|
||||||
private static final int BUFFER_SIZE = 2048;
|
private static final int BUFFER_SIZE = 2048;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param in Merged .ts file via {@link ru.vtosters.lite.music.converter.ts.TSMerger}
|
||||||
|
* @param out Output .mp3 file
|
||||||
|
* @param track Track to be converted
|
||||||
|
* @return True if success, else false
|
||||||
|
*/
|
||||||
|
public static boolean convert(File in, String out, MusicTrack track) {
|
||||||
|
checkFFMpegLibs();
|
||||||
|
|
||||||
|
|
||||||
|
// convert .ts file to .mp3 file via ffmpeg
|
||||||
|
var sb = new StringBuilder();
|
||||||
|
sb.append("-y -i \"").append(in.getAbsolutePath()).append("\"");
|
||||||
|
sb.append(" -map 0 -dn ");
|
||||||
|
//sb.append(" -loglevel error");
|
||||||
|
sb.append(" -hide_banner");
|
||||||
|
sb.append(" -write_id3v2 1");
|
||||||
|
|
||||||
|
String title = null;
|
||||||
|
|
||||||
|
if (track.f != null) {
|
||||||
|
title = track.f;
|
||||||
|
if (!track.g.isEmpty()) {
|
||||||
|
title += " (" + track.g + ")";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (title != null) {
|
||||||
|
sb.append(" -metadata title=\"").append(IOUtils.getValidFileName(title)).append("\"");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (track.L != null) {
|
||||||
|
sb.append(" -metadata artist=\"").append(track.L.stream().map(Artist::w1).collect(Collectors.joining(", "))).append("\"");
|
||||||
|
} else if (track.C != null) {
|
||||||
|
sb.append(" -metadata artist=\"").append(track.C).append("\"");
|
||||||
|
}
|
||||||
|
if (track.I != null) {
|
||||||
|
sb.append(" -metadata album=\"").append(track.I.getTitle()).append("\"");
|
||||||
|
}
|
||||||
|
|
||||||
|
sb.append(" -c copy \"").append(out).append("\"");
|
||||||
|
|
||||||
|
var command = sb.toString();
|
||||||
|
|
||||||
|
var session = FFmpegKit.execute(command);
|
||||||
|
var rc = session.getReturnCode();
|
||||||
|
|
||||||
|
if (ReturnCode.isSuccess(rc)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
Log.e("FFMpeg", "FFmpegKit failed with return code " + rc);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
private static void copyAssets() {
|
private static void copyAssets() {
|
||||||
try {
|
try {
|
||||||
String[] files = AndroidUtils.getGlobalContext().getAssets().list("ffmpeg");
|
String[] files = AndroidUtils.getGlobalContext().getAssets().list("ffmpeg");
|
||||||
@@ -45,40 +103,4 @@ public class FFMpeg {
|
|||||||
copyAssets();
|
copyAssets();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean convert(String in, String out) {
|
|
||||||
checkFFMpegLibs();
|
|
||||||
|
|
||||||
// write the list of all .ts files to a txt file in "in" directory
|
|
||||||
var list = new File(in);
|
|
||||||
var listFile = new File(list, "list.txt");
|
|
||||||
try {
|
|
||||||
listFile.createNewFile();
|
|
||||||
var writer = new java.io.FileWriter(listFile);
|
|
||||||
for (var file : list.listFiles()) {
|
|
||||||
if (file.getName().endsWith(".ts")) {
|
|
||||||
writer.write("file " + file.getName() + "\n");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
writer.close();
|
|
||||||
} catch (IOException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
|
|
||||||
// concatenate .ts files to a single .ts file
|
|
||||||
FFmpegKit.execute("-f concat -safe 0 -i " + in + "/list.txt -c copy " + in + "/all.ts");
|
|
||||||
|
|
||||||
// convert .ts file to .mp3 file via ffmpeg
|
|
||||||
var session = FFmpegKit.execute("-i " + in + "/all.ts -f mp3 -acodec mp3 -q:a 0 -y '" + out + "'");
|
|
||||||
var rc = session.getReturnCode();
|
|
||||||
|
|
||||||
if (ReturnCode.isSuccess(rc)) {
|
|
||||||
// remove temp files
|
|
||||||
IOUtils.deleteRecursive(new File(in));
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
Log.e("FFMpeg", "FFmpegKit failed with return code " + rc);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,65 @@
|
|||||||
|
package ru.vtosters.lite.music.converter.ts;
|
||||||
|
|
||||||
|
import android.os.Build;
|
||||||
|
|
||||||
|
import java.io.ByteArrayOutputStream;
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileOutputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.nio.file.Files;
|
||||||
|
import java.util.Arrays;
|
||||||
|
|
||||||
|
import ru.vtosters.lite.utils.IOUtils;
|
||||||
|
|
||||||
|
public class TSMerger {
|
||||||
|
/**
|
||||||
|
* Merge multiple .ts files into one .ts file
|
||||||
|
*
|
||||||
|
* @param in Directory with .ts files
|
||||||
|
* @return True if success, else false
|
||||||
|
*/
|
||||||
|
public static boolean merge(File in, File out) {
|
||||||
|
var tsesList = in.listFiles();
|
||||||
|
|
||||||
|
if (tsesList == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
var mergedByteArrayStream = new ByteArrayOutputStream();
|
||||||
|
|
||||||
|
Arrays.sort(tsesList, (o1, o2) -> {
|
||||||
|
var index1 = Integer.parseInt(o1.getName().split("-")[1]);
|
||||||
|
var index2 = Integer.parseInt(o2.getName().split("-")[1]);
|
||||||
|
return index1 - index2;
|
||||||
|
});
|
||||||
|
|
||||||
|
for (var file : tsesList) {
|
||||||
|
if (file.getName().endsWith(".ts")) {
|
||||||
|
try {
|
||||||
|
mergedByteArrayStream.write(IOUtils.readAllBytes(file));
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||||
|
try {
|
||||||
|
Files.write(out.toPath(), mergedByteArrayStream.toByteArray());
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
try (FileOutputStream fos = new FileOutputStream(out)) {
|
||||||
|
fos.write(mergedByteArrayStream.toByteArray());
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,82 @@
|
|||||||
|
package ru.vtosters.lite.music.downloader;
|
||||||
|
|
||||||
|
import static ru.vtosters.lite.hooks.DateHook.getLocale;
|
||||||
|
import static ru.vtosters.lite.proxy.ProxyUtils.getApi;
|
||||||
|
import static ru.vtosters.lite.utils.AccountManagerUtils.getUserId;
|
||||||
|
import static ru.vtosters.lite.utils.AccountManagerUtils.getUserToken;
|
||||||
|
|
||||||
|
import android.util.Log;
|
||||||
|
|
||||||
|
import com.vk.core.network.Network;
|
||||||
|
import com.vk.core.util.DeviceIdProvider;
|
||||||
|
import com.vk.dto.music.MusicTrack;
|
||||||
|
|
||||||
|
import org.json.JSONException;
|
||||||
|
import org.json.JSONObject;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.concurrent.ExecutionException;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
import java8.util.concurrent.CompletableFuture;
|
||||||
|
import okhttp3.Headers;
|
||||||
|
import okhttp3.OkHttpClient;
|
||||||
|
import okhttp3.Request;
|
||||||
|
import ru.vtosters.lite.utils.AndroidUtils;
|
||||||
|
|
||||||
|
public class AudioGet {
|
||||||
|
public static List<MusicTrack> getAudios() {
|
||||||
|
var tracks = requestAudios(0);
|
||||||
|
return tracks != null ? tracks.stream().filter(track -> !track.D.isEmpty()).collect(Collectors.toList()) : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static List<MusicTrack> requestAudios(int offset) {
|
||||||
|
var audioCount = 1000;
|
||||||
|
var requestUrl = "https://" + getApi() + "/method/audio.get" +
|
||||||
|
"?v=5.119" +
|
||||||
|
"&https=1" +
|
||||||
|
"&count=" + audioCount +
|
||||||
|
"&device_id=" + DeviceIdProvider.d(AndroidUtils.getGlobalContext()) +
|
||||||
|
"&owner_id=" + getUserId() +
|
||||||
|
"&access_key=" + getUserToken() +
|
||||||
|
"&lang=" + getLocale() +
|
||||||
|
"&offset=" + offset +
|
||||||
|
"&access_token=" + getUserToken();
|
||||||
|
|
||||||
|
var request = new Request.a()
|
||||||
|
.b(requestUrl)
|
||||||
|
.a(Headers.a("User-Agent", Network.l.c().a(), "Content-Type", "application/x-www-form-urlencoded; charset=utf-8")).a();
|
||||||
|
|
||||||
|
try {
|
||||||
|
var response = CompletableFuture.supplyAsync(() -> {
|
||||||
|
try {
|
||||||
|
return new OkHttpClient().a(request).execute().a().g();
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
).get();
|
||||||
|
var jsonObj = new JSONObject(response);
|
||||||
|
if (!jsonObj.has("response"))
|
||||||
|
return null;
|
||||||
|
Log.d("AudioGet", jsonObj.toString());
|
||||||
|
var audios = new JSONObject(response).getJSONObject("response").getJSONArray("items");
|
||||||
|
var tracks = new ArrayList<MusicTrack>();
|
||||||
|
for (int i = 0; i < audios.length(); i++) {
|
||||||
|
var track = new MusicTrack(audios.getJSONObject(i));
|
||||||
|
tracks.add(track);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tracks.size() == audioCount) {
|
||||||
|
tracks.addAll(requestAudios(offset + audioCount));
|
||||||
|
}
|
||||||
|
|
||||||
|
return tracks;
|
||||||
|
} catch (JSONException | ExecutionException | InterruptedException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,76 @@
|
|||||||
|
package ru.vtosters.lite.music.downloader;
|
||||||
|
|
||||||
|
import android.util.Log;
|
||||||
|
|
||||||
|
import com.vk.dto.music.MusicTrack;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
|
|
||||||
|
import ru.vtosters.lite.music.Callback;
|
||||||
|
import ru.vtosters.lite.music.cache.CacheDatabaseDelegate;
|
||||||
|
|
||||||
|
public class PlaylistDownloader {
|
||||||
|
public static void downloadPlaylist(List<MusicTrack> playlist, String playlistName, String path, Callback callback) {
|
||||||
|
File outDir = new File(path);
|
||||||
|
if (!outDir.exists())
|
||||||
|
if (outDir.mkdirs())
|
||||||
|
Log.v("PlaylistDownloader", "Directory created");
|
||||||
|
else
|
||||||
|
Log.e("PlaylistDownloader", "Directory creation failed");
|
||||||
|
|
||||||
|
var downloadedTracks = new AtomicInteger(0);
|
||||||
|
|
||||||
|
for (MusicTrack musicTrack : playlist) {
|
||||||
|
TrackDownloader.downloadTrack(musicTrack, path, new Callback() {
|
||||||
|
@Override
|
||||||
|
public void onProgress(int progress) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onSuccess() {
|
||||||
|
var currentProgress = downloadedTracks.incrementAndGet();
|
||||||
|
callback.onProgress(currentProgress);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onFailure() {
|
||||||
|
callback.onFailure();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onSizeReceived(long size, long header) {
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void cachePlaylist(List<MusicTrack> playlist, Callback callback) {
|
||||||
|
var downloadedTracks = new AtomicInteger(0);
|
||||||
|
|
||||||
|
for (MusicTrack musicTrack : playlist) {
|
||||||
|
TrackDownloader.cacheTrack(musicTrack, new Callback() {
|
||||||
|
@Override
|
||||||
|
public void onProgress(int progress) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onSuccess() {
|
||||||
|
var currentProgress = downloadedTracks.incrementAndGet();
|
||||||
|
callback.onProgress(currentProgress);
|
||||||
|
CacheDatabaseDelegate.insertTrack(musicTrack);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onFailure() {
|
||||||
|
callback.onFailure();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onSizeReceived(long size, long header) {
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,47 @@
|
|||||||
|
package ru.vtosters.lite.music.downloader;
|
||||||
|
|
||||||
|
import com.vk.dto.music.MusicTrack;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.net.URL;
|
||||||
|
|
||||||
|
import bruhcollective.itaysonlab.libvkx.client.LibVKXClient;
|
||||||
|
import ru.vtosters.lite.music.cache.FileCacheImplementation;
|
||||||
|
import ru.vtosters.lite.utils.IOUtils;
|
||||||
|
|
||||||
|
public class ThumbnailDownloader {
|
||||||
|
|
||||||
|
public static void downloadThumbnails(MusicTrack track)
|
||||||
|
throws IOException {
|
||||||
|
var obj = track.J();
|
||||||
|
var trackId = LibVKXClient.asId(track);
|
||||||
|
|
||||||
|
if (!obj.has("album")) return;
|
||||||
|
var album = obj.optJSONObject("album");
|
||||||
|
|
||||||
|
if (!album.has("thumb")) return;
|
||||||
|
var thumb = album.optJSONObject("thumb");
|
||||||
|
|
||||||
|
if (thumb.has("sizes")) {
|
||||||
|
var sizes = thumb.optJSONArray("sizes");
|
||||||
|
for (int i = 0; i < sizes.length(); i++) {
|
||||||
|
var size = sizes.optJSONObject(i);
|
||||||
|
var width = size.optInt("width");
|
||||||
|
var src = size.optString("src");
|
||||||
|
downloadThumbnail(src, width, trackId);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
var names = thumb.names();
|
||||||
|
for (int i = 0; i < names.length(); i++) {
|
||||||
|
var name = names.optString(i);
|
||||||
|
downloadThumbnail(thumb.optString(name), Integer.parseInt(name.substring(6)), trackId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void downloadThumbnail(String url, int res, String trackId)
|
||||||
|
throws IOException {
|
||||||
|
var data = IOUtils.readAllBytes(new URL(url).openStream());
|
||||||
|
IOUtils.writeToFile(FileCacheImplementation.getTrackThumbnail(trackId, res), data);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,34 @@
|
|||||||
|
package ru.vtosters.lite.music.downloader;
|
||||||
|
|
||||||
|
import android.util.Log;
|
||||||
|
|
||||||
|
import com.vk.dto.music.MusicTrack;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
|
||||||
|
import bruhcollective.itaysonlab.libvkx.client.LibVKXClient;
|
||||||
|
import ru.vtosters.lite.music.Callback;
|
||||||
|
import ru.vtosters.lite.music.M3UDownloader;
|
||||||
|
import ru.vtosters.lite.music.cache.FileCacheImplementation;
|
||||||
|
import ru.vtosters.lite.music.interfaces.ITrackDownloader;
|
||||||
|
|
||||||
|
public class TrackDownloader {
|
||||||
|
public static void downloadTrack(MusicTrack track, String path, Callback callback) {
|
||||||
|
download(track, path, callback, M3UDownloader.getInstance(), false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void cacheTrack(MusicTrack track, Callback callback) {
|
||||||
|
var path = FileCacheImplementation.getTrackFolder(LibVKXClient.asId(track)).getAbsolutePath();
|
||||||
|
download(track, path, callback, M3UDownloader.getInstance(), true);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void download(MusicTrack track, String path, Callback callback, ITrackDownloader downloader, boolean cache) {
|
||||||
|
File outDir = new File(path);
|
||||||
|
if (!outDir.exists())
|
||||||
|
if (outDir.mkdir())
|
||||||
|
Log.v("TrackDownloader", "Directory created");
|
||||||
|
else
|
||||||
|
Log.e("TrackDownloader", "Directory creation failed");
|
||||||
|
downloader.downloadTrack(track, outDir, callback, cache);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
package ru.vtosters.lite.music.interfaces;
|
||||||
|
|
||||||
|
import com.vk.dto.music.MusicTrack;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
|
||||||
|
import ru.vtosters.lite.music.Callback;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Interface for track downloaders
|
||||||
|
*/
|
||||||
|
public interface ITrackDownloader {
|
||||||
|
/**
|
||||||
|
* Download track
|
||||||
|
*
|
||||||
|
* @param track Music track
|
||||||
|
* @param outDir Directory where to download the track
|
||||||
|
* @param callback Callback to call when download status changes
|
||||||
|
*/
|
||||||
|
void downloadTrack(MusicTrack track, File outDir, Callback callback, boolean cache);
|
||||||
|
}
|
||||||
@@ -0,0 +1,73 @@
|
|||||||
|
package ru.vtosters.lite.music.notification;
|
||||||
|
|
||||||
|
import static ru.vtosters.lite.utils.AndroidUtils.getString;
|
||||||
|
|
||||||
|
import android.app.Notification;
|
||||||
|
import android.os.Build;
|
||||||
|
|
||||||
|
import androidx.core.app.NotificationCompat;
|
||||||
|
import androidx.core.app.NotificationManagerCompat;
|
||||||
|
|
||||||
|
import com.vk.dto.music.MusicTrack;
|
||||||
|
|
||||||
|
import ru.vtosters.lite.downloaders.notifications.NotificationChannels;
|
||||||
|
import ru.vtosters.lite.utils.AccountManagerUtils;
|
||||||
|
import ru.vtosters.lite.utils.AndroidUtils;
|
||||||
|
|
||||||
|
public class MusicNotificationBuilder {
|
||||||
|
private static final NotificationManagerCompat notificationManager = NotificationChannels.getNotificationManager();
|
||||||
|
|
||||||
|
public static NotificationCompat.Builder buildDownloadNotification(MusicTrack track, int id) {
|
||||||
|
var notificationBuilder = new NotificationCompat.Builder(AndroidUtils.getGlobalContext(), NotificationChannels.MUSIC_DOWNLOAD_CHANNEL_ID)
|
||||||
|
.setSmallIcon(android.R.drawable.stat_sys_download)
|
||||||
|
.setContentTitle(getString("audio_downloading"))
|
||||||
|
.setContentText(track.toString())
|
||||||
|
.setPriority(NotificationCompat.PRIORITY_LOW)
|
||||||
|
.setCategory(NotificationCompat.CATEGORY_PROGRESS)
|
||||||
|
.setAutoCancel(true)
|
||||||
|
.setProgress(100, 0, false);
|
||||||
|
notificationManager.notify(id, notificationBuilder.build());
|
||||||
|
return notificationBuilder;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static NotificationCompat.Builder buildPlaylistDownloadNotification(String playlistName, int id) {
|
||||||
|
var notificationBuilder = new NotificationCompat.Builder(AndroidUtils.getGlobalContext(), NotificationChannels.MUSIC_PLAYLIST_DOWNLOAD_CHANNEL_ID)
|
||||||
|
.setSmallIcon(android.R.drawable.stat_sys_download)
|
||||||
|
.setContentTitle(getString("playlist_downloading") + " «" + playlistName + "»")
|
||||||
|
.setContentText(playlistName)
|
||||||
|
.setPriority(NotificationCompat.PRIORITY_LOW)
|
||||||
|
.setCategory(NotificationCompat.CATEGORY_PROGRESS)
|
||||||
|
.setAutoCancel(true)
|
||||||
|
.setProgress(100, 0, false);
|
||||||
|
notificationManager.notify(id, notificationBuilder.build());
|
||||||
|
return notificationBuilder;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static NotificationCompat.Builder buildAllAudiosDownloadNotification(int id) {
|
||||||
|
var notificationBuilder = new NotificationCompat.Builder(AndroidUtils.getGlobalContext(), NotificationChannels.MUSIC_PLAYLIST_DOWNLOAD_CHANNEL_ID)
|
||||||
|
.setSmallIcon(android.R.drawable.stat_sys_download)
|
||||||
|
.setContentTitle(getString("notf_audio_dl_user") + " " + AccountManagerUtils.getUsername())
|
||||||
|
.setContentText(getString("all_audio"))
|
||||||
|
.setPriority(NotificationCompat.PRIORITY_LOW)
|
||||||
|
.setCategory(NotificationCompat.CATEGORY_PROGRESS)
|
||||||
|
.setAutoCancel(true)
|
||||||
|
.setProgress(100, 0, false);
|
||||||
|
notificationManager.notify(id, notificationBuilder.build());
|
||||||
|
return notificationBuilder;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void notifySavingToCache(MusicTrack track) {
|
||||||
|
Notification.Builder builder;
|
||||||
|
|
||||||
|
if (Build.VERSION.SDK_INT >= 26) {
|
||||||
|
builder = new Notification.Builder(AndroidUtils.getGlobalContext(), NotificationChannels.MUSIC_DOWNLOAD_CHANNEL_ID);
|
||||||
|
builder.setVisibility(Notification.VISIBILITY_PUBLIC);
|
||||||
|
} else builder = new Notification.Builder(AndroidUtils.getGlobalContext());
|
||||||
|
|
||||||
|
builder.setSmallIcon(com.vtosters.lite.R.drawable.ic_download_outline_28)
|
||||||
|
.setShowWhen(false)
|
||||||
|
.setContentTitle(getString("cached_track") + ": " + track.toString());
|
||||||
|
|
||||||
|
notificationManager.notify(track.y1().hashCode(), builder.build());
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,4 +1,5 @@
|
|||||||
package ru.vtosters.lite.proxy;
|
package ru.vtosters.lite.proxy;
|
||||||
|
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
@@ -8,10 +9,10 @@ import java.util.Arrays;
|
|||||||
import okhttp3.OkHttpClient;
|
import okhttp3.OkHttpClient;
|
||||||
import okhttp3.Request;
|
import okhttp3.Request;
|
||||||
|
|
||||||
public class GithubList{
|
public class GithubList {
|
||||||
private static final OkHttpClient mClient = new OkHttpClient();
|
private static final OkHttpClient mClient = new OkHttpClient();
|
||||||
|
|
||||||
public static ArrayList<String> getProxy(String url, String proxyname) throws IOException{
|
public static ArrayList<String> getProxy(String url, String proxyname) throws IOException {
|
||||||
Request link = new Request.a()
|
Request link = new Request.a()
|
||||||
.b(url)
|
.b(url)
|
||||||
.a();
|
.a();
|
||||||
|
|||||||
@@ -22,8 +22,8 @@ import ru.vtosters.lite.proxy.https.CustomHttps;
|
|||||||
import ru.vtosters.lite.proxy.socks.CustomSocks;
|
import ru.vtosters.lite.proxy.socks.CustomSocks;
|
||||||
import ru.vtosters.lite.proxy.socks.Zaborona;
|
import ru.vtosters.lite.proxy.socks.Zaborona;
|
||||||
|
|
||||||
public class ProxyUtils{
|
public class ProxyUtils {
|
||||||
public static String getApi(){
|
public static String getApi() {
|
||||||
var proxyapi = getPrefsValue("proxyapi");
|
var proxyapi = getPrefsValue("proxyapi");
|
||||||
|
|
||||||
if (isVikaProxyEnabled()) {
|
if (isVikaProxyEnabled()) {
|
||||||
@@ -37,7 +37,7 @@ public class ProxyUtils{
|
|||||||
return "api.vk.com";
|
return "api.vk.com";
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String getOauth(){
|
public static String getOauth() {
|
||||||
var oauth = getPrefsValue("proxyoauth");
|
var oauth = getPrefsValue("proxyoauth");
|
||||||
|
|
||||||
if (isVikaProxyEnabled()) {
|
if (isVikaProxyEnabled()) {
|
||||||
@@ -51,7 +51,7 @@ public class ProxyUtils{
|
|||||||
return "oauth.vk.com";
|
return "oauth.vk.com";
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String getStatic(){
|
public static String getStatic() {
|
||||||
var staticapi = getPrefsValue("proxystatic");
|
var staticapi = getPrefsValue("proxystatic");
|
||||||
|
|
||||||
if (isVikaProxyEnabled()) {
|
if (isVikaProxyEnabled()) {
|
||||||
@@ -65,27 +65,27 @@ public class ProxyUtils{
|
|||||||
return "static.vk.com";
|
return "static.vk.com";
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Boolean isAnyProxyEnabled(){
|
public static Boolean isAnyProxyEnabled() {
|
||||||
return isApiProxyEnabled() || isVikaProxyEnabled();
|
return isApiProxyEnabled() || isVikaProxyEnabled();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Boolean isZaboronaEnabled(){
|
public static Boolean isZaboronaEnabled() {
|
||||||
return getPrefsValue("proxy").equals("zaborona");
|
return getPrefsValue("proxy").equals("zaborona");
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Boolean isRandomProxyEnabled(){
|
public static Boolean isRandomProxyEnabled() {
|
||||||
return getPrefsValue("proxy").equals("randomproxy");
|
return getPrefsValue("proxy").equals("randomproxy");
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Boolean isApiProxyEnabled(){
|
public static Boolean isApiProxyEnabled() {
|
||||||
return getPrefsValue("proxy").equals("apiproxy");
|
return getPrefsValue("proxy").equals("apiproxy");
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Boolean isVikaProxyEnabled(){
|
public static Boolean isVikaProxyEnabled() {
|
||||||
return getPrefsValue("proxy").equals("vika");
|
return getPrefsValue("proxy").equals("vika");
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void forceProxyApplying(){
|
public static void forceProxyApplying() {
|
||||||
Log.d("Proxy", "Setting proxy...");
|
Log.d("Proxy", "Setting proxy...");
|
||||||
try {
|
try {
|
||||||
var context = getGlobalContext().getApplicationContext();
|
var context = getGlobalContext().getApplicationContext();
|
||||||
@@ -128,12 +128,12 @@ public class ProxyUtils{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean hasProxy(String list){
|
public static boolean hasProxy(String list) {
|
||||||
return list.contains(":"); // proxy format: ip:port
|
return list.contains(":"); // proxy format: ip:port
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void setProxy() throws IOException{
|
public static void setProxy() throws IOException {
|
||||||
switch(getPrefsValue("proxy")) {
|
switch (getPrefsValue("proxy")) {
|
||||||
case "zaborona":
|
case "zaborona":
|
||||||
Zaborona.loadProxy();
|
Zaborona.loadProxy();
|
||||||
break;
|
break;
|
||||||
@@ -155,7 +155,7 @@ public class ProxyUtils{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void resetProxy(){
|
public static void resetProxy() {
|
||||||
clearProperty("https.proxyHost");
|
clearProperty("https.proxyHost");
|
||||||
clearProperty("https.proxyPort");
|
clearProperty("https.proxyPort");
|
||||||
clearProperty("https.proxyUser");
|
clearProperty("https.proxyUser");
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
package ru.vtosters.lite.proxy;
|
package ru.vtosters.lite.proxy;
|
||||||
|
|
||||||
import static ru.vtosters.lite.proxy.ProxyUtils.forceProxyApplying;
|
import static ru.vtosters.lite.proxy.ProxyUtils.forceProxyApplying;
|
||||||
import static ru.vtosters.lite.proxy.ProxyUtils.resetProxy;
|
import static ru.vtosters.lite.proxy.ProxyUtils.resetProxy;
|
||||||
import static ru.vtosters.lite.utils.AndroidUtils.edit;
|
import static ru.vtosters.lite.utils.AndroidUtils.edit;
|
||||||
@@ -11,19 +12,19 @@ import ru.vtosters.lite.proxy.socks.Jetkai;
|
|||||||
import ru.vtosters.lite.proxy.socks.Roosterkid;
|
import ru.vtosters.lite.proxy.socks.Roosterkid;
|
||||||
import ru.vtosters.lite.proxy.socks.TheSpeedX;
|
import ru.vtosters.lite.proxy.socks.TheSpeedX;
|
||||||
|
|
||||||
public class RandomProxy{
|
public class RandomProxy {
|
||||||
public static String type = preferences.getString("random_type", "none");
|
public static String type = preferences.getString("random_type", "none");
|
||||||
public static String host = preferences.getString("random_host", "");
|
public static String host = preferences.getString("random_host", "");
|
||||||
public static boolean showProxyResult = false;
|
public static boolean showProxyResult = false;
|
||||||
|
|
||||||
public static void loadProxy() throws IOException{
|
public static void loadProxy() throws IOException {
|
||||||
if (host.isEmpty()) {
|
if (host.isEmpty()) {
|
||||||
getProxy();
|
getProxy();
|
||||||
loadProxy();
|
loadProxy();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch(type) {
|
switch (type) {
|
||||||
case "socks":
|
case "socks":
|
||||||
System.setProperty("socksProxyHost", host.split(":")[0]);
|
System.setProperty("socksProxyHost", host.split(":")[0]);
|
||||||
System.setProperty("socksProxyPort", host.split(":")[1]);
|
System.setProperty("socksProxyPort", host.split(":")[1]);
|
||||||
@@ -39,7 +40,7 @@ public class RandomProxy{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void setupNewProxy() throws IOException{
|
public static void setupNewProxy() throws IOException {
|
||||||
edit().putString("random_type", "none").putString("random_host", "").commit();
|
edit().putString("random_type", "none").putString("random_host", "").commit();
|
||||||
|
|
||||||
resetProxy();
|
resetProxy();
|
||||||
@@ -50,10 +51,10 @@ public class RandomProxy{
|
|||||||
edit().putString("proxy", "randomproxy").commit();
|
edit().putString("proxy", "randomproxy").commit();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void getProxy() throws IOException{
|
public static void getProxy() throws IOException {
|
||||||
var random = new java.util.Random();
|
var random = new java.util.Random();
|
||||||
var randomInt = random.nextInt(7);
|
var randomInt = random.nextInt(7);
|
||||||
switch(randomInt) {
|
switch (randomInt) {
|
||||||
case 0:
|
case 0:
|
||||||
Hookzof.loadProxy();
|
Hookzof.loadProxy();
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -1,12 +1,13 @@
|
|||||||
package ru.vtosters.lite.proxy.api;
|
package ru.vtosters.lite.proxy.api;
|
||||||
|
|
||||||
import static ru.vtosters.lite.proxy.ProxyUtils.isAnyProxyEnabled;
|
import static ru.vtosters.lite.proxy.ProxyUtils.isAnyProxyEnabled;
|
||||||
import static ru.vtosters.lite.proxy.ProxyUtils.isVikaProxyEnabled;
|
import static ru.vtosters.lite.proxy.ProxyUtils.isVikaProxyEnabled;
|
||||||
import static ru.vtosters.lite.utils.AndroidUtils.getPrefsValue;
|
import static ru.vtosters.lite.utils.AndroidUtils.getPrefsValue;
|
||||||
|
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
public class ApiProxy{
|
public class ApiProxy {
|
||||||
public static String linkReplacer(String link){
|
public static String linkReplacer(String link) {
|
||||||
var vkapi = "api.vk.com";
|
var vkapi = "api.vk.com";
|
||||||
var oauth = "oauth.vk.com";
|
var oauth = "oauth.vk.com";
|
||||||
var vkstatic = "static.vk.com";
|
var vkstatic = "static.vk.com";
|
||||||
@@ -59,7 +60,7 @@ public class ApiProxy{
|
|||||||
return str;
|
return str;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String getAwayPhpCom(){
|
public static String getAwayPhpCom() {
|
||||||
var proxyapi = getPrefsValue("proxyapi");
|
var proxyapi = getPrefsValue("proxyapi");
|
||||||
|
|
||||||
if (isVikaProxyEnabled()) {
|
if (isVikaProxyEnabled()) {
|
||||||
|
|||||||
@@ -1,20 +1,21 @@
|
|||||||
package ru.vtosters.lite.proxy.api;
|
package ru.vtosters.lite.proxy.api;
|
||||||
|
|
||||||
import static ru.vtosters.lite.utils.Preferences.getBoolValue;
|
import static ru.vtosters.lite.utils.Preferences.getBoolValue;
|
||||||
|
|
||||||
public class VikaMobile{
|
public class VikaMobile {
|
||||||
public static String getApiHost(){
|
public static String getApiHost() {
|
||||||
return isAlternativeHost() ? "vk-api-proxy.vikamobile.ru" : "vk-api-proxy.symbian.live";
|
return isAlternativeHost() ? "vk-api-proxy.vikamobile.ru" : "vk-api-proxy.symbian.live";
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String getOauthHost(){
|
public static String getOauthHost() {
|
||||||
return isAlternativeHost() ? "vk-oauth-proxy.vikamobile.ru" : "vk-oauth-proxy.symbian.live";
|
return isAlternativeHost() ? "vk-oauth-proxy.vikamobile.ru" : "vk-oauth-proxy.symbian.live";
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String getStaticHost(){
|
public static String getStaticHost() {
|
||||||
return isAlternativeHost() ? "vk-static-proxy.vikamobile.ru" : "vk-static-proxy.symbian.live";
|
return isAlternativeHost() ? "vk-static-proxy.vikamobile.ru" : "vk-static-proxy.symbian.live";
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Boolean isAlternativeHost(){
|
public static Boolean isAlternativeHost() {
|
||||||
return getBoolValue("altervika", false);
|
return getBoolValue("altervika", false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,9 +1,10 @@
|
|||||||
package ru.vtosters.lite.proxy.http;
|
package ru.vtosters.lite.proxy.http;
|
||||||
|
|
||||||
import static ru.vtosters.lite.proxy.ProxyUtils.forceProxyApplying;
|
import static ru.vtosters.lite.proxy.ProxyUtils.forceProxyApplying;
|
||||||
import static ru.vtosters.lite.utils.AndroidUtils.getPrefsValue;
|
import static ru.vtosters.lite.utils.AndroidUtils.getPrefsValue;
|
||||||
|
|
||||||
public class CustomHttp{
|
public class CustomHttp {
|
||||||
public static void loadProxy(){
|
public static void loadProxy() {
|
||||||
System.setProperty("http.proxyHost", proxyHostHTTP());
|
System.setProperty("http.proxyHost", proxyHostHTTP());
|
||||||
System.setProperty("http.proxyPort", proxyPortHTTP());
|
System.setProperty("http.proxyPort", proxyPortHTTP());
|
||||||
System.setProperty("http.proxyUser", proxyUserHTTP());
|
System.setProperty("http.proxyUser", proxyUserHTTP());
|
||||||
@@ -11,22 +12,22 @@ public class CustomHttp{
|
|||||||
forceProxyApplying();
|
forceProxyApplying();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static String proxyHostHTTP(){
|
private static String proxyHostHTTP() {
|
||||||
var string = getPrefsValue("proxyHostHTTP");
|
var string = getPrefsValue("proxyHostHTTP");
|
||||||
return string.isEmpty() ? "192.168.0.1" : string;
|
return string.isEmpty() ? "192.168.0.1" : string;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static String proxyPortHTTP(){
|
private static String proxyPortHTTP() {
|
||||||
var string = getPrefsValue("proxyPortHTTP");
|
var string = getPrefsValue("proxyPortHTTP");
|
||||||
return string.isEmpty() ? "8888" : string;
|
return string.isEmpty() ? "8888" : string;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static String proxyUserHTTP(){
|
private static String proxyUserHTTP() {
|
||||||
var string = getPrefsValue("proxyUserHTTP");
|
var string = getPrefsValue("proxyUserHTTP");
|
||||||
return string.isEmpty() ? "" : string;
|
return string.isEmpty() ? "" : string;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static String proxyPassHTTP(){
|
private static String proxyPassHTTP() {
|
||||||
var string = getPrefsValue("proxyPassHTTP");
|
var string = getPrefsValue("proxyPassHTTP");
|
||||||
return string.isEmpty() ? "" : string;
|
return string.isEmpty() ? "" : string;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
package ru.vtosters.lite.proxy.http;
|
package ru.vtosters.lite.proxy.http;
|
||||||
|
|
||||||
import static ru.vtosters.lite.proxy.GithubList.getProxy;
|
import static ru.vtosters.lite.proxy.GithubList.getProxy;
|
||||||
import static ru.vtosters.lite.proxy.ProxyUtils.forceProxyApplying;
|
import static ru.vtosters.lite.proxy.ProxyUtils.forceProxyApplying;
|
||||||
import static ru.vtosters.lite.proxy.ProxyUtils.hasProxy;
|
import static ru.vtosters.lite.proxy.ProxyUtils.hasProxy;
|
||||||
@@ -13,10 +14,10 @@ import java.util.ArrayList;
|
|||||||
import ru.vtosters.lite.proxy.RandomProxy;
|
import ru.vtosters.lite.proxy.RandomProxy;
|
||||||
import ru.vtosters.lite.utils.AndroidUtils;
|
import ru.vtosters.lite.utils.AndroidUtils;
|
||||||
|
|
||||||
public class Jetkai{
|
public class Jetkai {
|
||||||
private static final String TAG = "Jetkai_Http";
|
private static final String TAG = "Jetkai_Http";
|
||||||
|
|
||||||
public static void loadProxy() throws IOException{
|
public static void loadProxy() throws IOException {
|
||||||
ArrayList<String> proxyList = getProxy("https://raw.githubusercontent.com/jetkai/proxy-list/main/online-proxies/txt/proxies-http.txt", TAG);
|
ArrayList<String> proxyList = getProxy("https://raw.githubusercontent.com/jetkai/proxy-list/main/online-proxies/txt/proxies-http.txt", TAG);
|
||||||
|
|
||||||
if (proxyList == null) {
|
if (proxyList == null) {
|
||||||
@@ -38,7 +39,7 @@ public class Jetkai{
|
|||||||
RandomProxy.showProxyResult = false;
|
RandomProxy.showProxyResult = false;
|
||||||
RandomProxy.showProxyResult = false;
|
RandomProxy.showProxyResult = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
edit().putString("random_type", "http").putString("random_host", proxy).commit();
|
edit().putString("random_type", "http").putString("random_host", proxy).commit();
|
||||||
|
|
||||||
System.setProperty("http.proxyHost", proxy.split(":")[0]);
|
System.setProperty("http.proxyHost", proxy.split(":")[0]);
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
package ru.vtosters.lite.proxy.http;
|
package ru.vtosters.lite.proxy.http;
|
||||||
|
|
||||||
import static ru.vtosters.lite.proxy.GithubList.getProxy;
|
import static ru.vtosters.lite.proxy.GithubList.getProxy;
|
||||||
import static ru.vtosters.lite.proxy.ProxyUtils.forceProxyApplying;
|
import static ru.vtosters.lite.proxy.ProxyUtils.forceProxyApplying;
|
||||||
import static ru.vtosters.lite.proxy.ProxyUtils.hasProxy;
|
import static ru.vtosters.lite.proxy.ProxyUtils.hasProxy;
|
||||||
@@ -13,10 +14,10 @@ import java.util.ArrayList;
|
|||||||
import ru.vtosters.lite.proxy.RandomProxy;
|
import ru.vtosters.lite.proxy.RandomProxy;
|
||||||
import ru.vtosters.lite.utils.AndroidUtils;
|
import ru.vtosters.lite.utils.AndroidUtils;
|
||||||
|
|
||||||
public class TheSpeedX{
|
public class TheSpeedX {
|
||||||
private static final String TAG = "TheSpeedX_Http";
|
private static final String TAG = "TheSpeedX_Http";
|
||||||
|
|
||||||
public static void loadProxy() throws IOException{
|
public static void loadProxy() throws IOException {
|
||||||
ArrayList<String> proxyList = getProxy("https://raw.githubusercontent.com/TheSpeedX/PROXY-List/master/http.txt", TAG);
|
ArrayList<String> proxyList = getProxy("https://raw.githubusercontent.com/TheSpeedX/PROXY-List/master/http.txt", TAG);
|
||||||
|
|
||||||
if (proxyList == null) {
|
if (proxyList == null) {
|
||||||
@@ -37,7 +38,7 @@ public class TheSpeedX{
|
|||||||
AndroidUtils.sendToast(getString("proxy_setup_success") + " " + proxy);
|
AndroidUtils.sendToast(getString("proxy_setup_success") + " " + proxy);
|
||||||
RandomProxy.showProxyResult = false;
|
RandomProxy.showProxyResult = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
edit().putString("random_type", "http").putString("random_host", proxy).commit();
|
edit().putString("random_type", "http").putString("random_host", proxy).commit();
|
||||||
|
|
||||||
System.setProperty("http.proxyHost", proxy.split(":")[0]);
|
System.setProperty("http.proxyHost", proxy.split(":")[0]);
|
||||||
|
|||||||
@@ -1,9 +1,10 @@
|
|||||||
package ru.vtosters.lite.proxy.https;
|
package ru.vtosters.lite.proxy.https;
|
||||||
|
|
||||||
import static ru.vtosters.lite.proxy.ProxyUtils.forceProxyApplying;
|
import static ru.vtosters.lite.proxy.ProxyUtils.forceProxyApplying;
|
||||||
import static ru.vtosters.lite.utils.AndroidUtils.getPrefsValue;
|
import static ru.vtosters.lite.utils.AndroidUtils.getPrefsValue;
|
||||||
|
|
||||||
public class CustomHttps{
|
public class CustomHttps {
|
||||||
public static void loadProxy(){
|
public static void loadProxy() {
|
||||||
System.setProperty("https.proxyHost", proxyHostHTTPS());
|
System.setProperty("https.proxyHost", proxyHostHTTPS());
|
||||||
System.setProperty("https.proxyPort", proxyPortHTTPS());
|
System.setProperty("https.proxyPort", proxyPortHTTPS());
|
||||||
System.setProperty("https.proxyUser", proxyUserHTTPS());
|
System.setProperty("https.proxyUser", proxyUserHTTPS());
|
||||||
@@ -11,22 +12,22 @@ public class CustomHttps{
|
|||||||
forceProxyApplying();
|
forceProxyApplying();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static String proxyHostHTTPS(){
|
private static String proxyHostHTTPS() {
|
||||||
var string = getPrefsValue("proxyHostHTTPS");
|
var string = getPrefsValue("proxyHostHTTPS");
|
||||||
return string.isEmpty() ? "192.168.0.1" : string;
|
return string.isEmpty() ? "192.168.0.1" : string;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static String proxyPortHTTPS(){
|
private static String proxyPortHTTPS() {
|
||||||
var string = getPrefsValue("proxyPortHTTPS");
|
var string = getPrefsValue("proxyPortHTTPS");
|
||||||
return string.isEmpty() ? "8888" : string;
|
return string.isEmpty() ? "8888" : string;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static String proxyUserHTTPS(){
|
private static String proxyUserHTTPS() {
|
||||||
var string = getPrefsValue("proxyUserHTTPS");
|
var string = getPrefsValue("proxyUserHTTPS");
|
||||||
return string.isEmpty() ? "" : string;
|
return string.isEmpty() ? "" : string;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static String proxyPassHTTPS(){
|
private static String proxyPassHTTPS() {
|
||||||
String string = getPrefsValue("proxyPassHTTPS");
|
String string = getPrefsValue("proxyPassHTTPS");
|
||||||
return string.isEmpty() ? "" : string;
|
return string.isEmpty() ? "" : string;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
package ru.vtosters.lite.proxy.https;
|
package ru.vtosters.lite.proxy.https;
|
||||||
|
|
||||||
import static ru.vtosters.lite.proxy.GithubList.getProxy;
|
import static ru.vtosters.lite.proxy.GithubList.getProxy;
|
||||||
import static ru.vtosters.lite.proxy.ProxyUtils.forceProxyApplying;
|
import static ru.vtosters.lite.proxy.ProxyUtils.forceProxyApplying;
|
||||||
import static ru.vtosters.lite.proxy.ProxyUtils.hasProxy;
|
import static ru.vtosters.lite.proxy.ProxyUtils.hasProxy;
|
||||||
@@ -13,10 +14,10 @@ import java.util.ArrayList;
|
|||||||
import ru.vtosters.lite.proxy.RandomProxy;
|
import ru.vtosters.lite.proxy.RandomProxy;
|
||||||
import ru.vtosters.lite.utils.AndroidUtils;
|
import ru.vtosters.lite.utils.AndroidUtils;
|
||||||
|
|
||||||
public class Jetkai{
|
public class Jetkai {
|
||||||
private static final String TAG = "Jetkai_Https";
|
private static final String TAG = "Jetkai_Https";
|
||||||
|
|
||||||
public static void loadProxy() throws IOException{
|
public static void loadProxy() throws IOException {
|
||||||
ArrayList<String> proxyList = getProxy("https://raw.githubusercontent.com/jetkai/proxy-list/main/online-proxies/txt/proxies-https.txt", TAG);
|
ArrayList<String> proxyList = getProxy("https://raw.githubusercontent.com/jetkai/proxy-list/main/online-proxies/txt/proxies-https.txt", TAG);
|
||||||
|
|
||||||
if (proxyList == null) {
|
if (proxyList == null) {
|
||||||
@@ -37,7 +38,7 @@ public class Jetkai{
|
|||||||
AndroidUtils.sendToast(getString("proxy_setup_success") + " " + proxy);
|
AndroidUtils.sendToast(getString("proxy_setup_success") + " " + proxy);
|
||||||
RandomProxy.showProxyResult = false;
|
RandomProxy.showProxyResult = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
edit().putString("random_type", "https").putString("random_host", proxy).commit();
|
edit().putString("random_type", "https").putString("random_host", proxy).commit();
|
||||||
|
|
||||||
System.setProperty("https.proxyHost", proxy.split(":")[0]);
|
System.setProperty("https.proxyHost", proxy.split(":")[0]);
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
package ru.vtosters.lite.proxy.https;
|
package ru.vtosters.lite.proxy.https;
|
||||||
|
|
||||||
import static ru.vtosters.lite.proxy.GithubList.getProxy;
|
import static ru.vtosters.lite.proxy.GithubList.getProxy;
|
||||||
import static ru.vtosters.lite.proxy.ProxyUtils.forceProxyApplying;
|
import static ru.vtosters.lite.proxy.ProxyUtils.forceProxyApplying;
|
||||||
import static ru.vtosters.lite.proxy.ProxyUtils.hasProxy;
|
import static ru.vtosters.lite.proxy.ProxyUtils.hasProxy;
|
||||||
@@ -13,10 +14,10 @@ import java.util.ArrayList;
|
|||||||
import ru.vtosters.lite.proxy.RandomProxy;
|
import ru.vtosters.lite.proxy.RandomProxy;
|
||||||
import ru.vtosters.lite.utils.AndroidUtils;
|
import ru.vtosters.lite.utils.AndroidUtils;
|
||||||
|
|
||||||
public class Roosterkid{
|
public class Roosterkid {
|
||||||
private static final String TAG = "Roosterkid_Https";
|
private static final String TAG = "Roosterkid_Https";
|
||||||
|
|
||||||
public static void loadProxy() throws IOException{
|
public static void loadProxy() throws IOException {
|
||||||
ArrayList<String> proxyList = getProxy("https://raw.githubusercontent.com/roosterkid/openproxylist/main/HTTPS_RAW.txt", TAG);
|
ArrayList<String> proxyList = getProxy("https://raw.githubusercontent.com/roosterkid/openproxylist/main/HTTPS_RAW.txt", TAG);
|
||||||
|
|
||||||
if (proxyList == null) {
|
if (proxyList == null) {
|
||||||
@@ -37,7 +38,7 @@ public class Roosterkid{
|
|||||||
AndroidUtils.sendToast(getString("proxy_setup_success") + " " + proxy);
|
AndroidUtils.sendToast(getString("proxy_setup_success") + " " + proxy);
|
||||||
RandomProxy.showProxyResult = false;
|
RandomProxy.showProxyResult = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
edit().putString("random_type", "https").putString("random_host", proxy).commit();
|
edit().putString("random_type", "https").putString("random_host", proxy).commit();
|
||||||
|
|
||||||
System.setProperty("https.proxyHost", proxy.split(":")[0]);
|
System.setProperty("https.proxyHost", proxy.split(":")[0]);
|
||||||
|
|||||||
@@ -1,20 +1,21 @@
|
|||||||
package ru.vtosters.lite.proxy.socks;
|
package ru.vtosters.lite.proxy.socks;
|
||||||
|
|
||||||
import static ru.vtosters.lite.proxy.ProxyUtils.forceProxyApplying;
|
import static ru.vtosters.lite.proxy.ProxyUtils.forceProxyApplying;
|
||||||
import static ru.vtosters.lite.utils.AndroidUtils.getPrefsValue;
|
import static ru.vtosters.lite.utils.AndroidUtils.getPrefsValue;
|
||||||
|
|
||||||
public class CustomSocks{
|
public class CustomSocks {
|
||||||
public static void loadProxy(){
|
public static void loadProxy() {
|
||||||
System.setProperty("socksProxyHost", proxyHostSocks());
|
System.setProperty("socksProxyHost", proxyHostSocks());
|
||||||
System.setProperty("socksProxyPort", proxyPortSocks());
|
System.setProperty("socksProxyPort", proxyPortSocks());
|
||||||
forceProxyApplying();
|
forceProxyApplying();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static String proxyHostSocks(){
|
private static String proxyHostSocks() {
|
||||||
var string = getPrefsValue("proxyHostSocks");
|
var string = getPrefsValue("proxyHostSocks");
|
||||||
return string.isEmpty() ? "192.168.0.1" : string;
|
return string.isEmpty() ? "192.168.0.1" : string;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static String proxyPortSocks(){
|
private static String proxyPortSocks() {
|
||||||
var string = getPrefsValue("proxyPortSocks");
|
var string = getPrefsValue("proxyPortSocks");
|
||||||
return string.isEmpty() ? "8888" : string;
|
return string.isEmpty() ? "8888" : string;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
package ru.vtosters.lite.proxy.socks;
|
package ru.vtosters.lite.proxy.socks;
|
||||||
|
|
||||||
import static ru.vtosters.lite.proxy.GithubList.getProxy;
|
import static ru.vtosters.lite.proxy.GithubList.getProxy;
|
||||||
import static ru.vtosters.lite.proxy.ProxyUtils.forceProxyApplying;
|
import static ru.vtosters.lite.proxy.ProxyUtils.forceProxyApplying;
|
||||||
import static ru.vtosters.lite.proxy.ProxyUtils.hasProxy;
|
import static ru.vtosters.lite.proxy.ProxyUtils.hasProxy;
|
||||||
@@ -13,10 +14,10 @@ import java.util.ArrayList;
|
|||||||
import ru.vtosters.lite.proxy.RandomProxy;
|
import ru.vtosters.lite.proxy.RandomProxy;
|
||||||
import ru.vtosters.lite.utils.AndroidUtils;
|
import ru.vtosters.lite.utils.AndroidUtils;
|
||||||
|
|
||||||
public class Hookzof{
|
public class Hookzof {
|
||||||
private static final String TAG = "Hookzof_Socks";
|
private static final String TAG = "Hookzof_Socks";
|
||||||
|
|
||||||
public static void loadProxy() throws IOException{
|
public static void loadProxy() throws IOException {
|
||||||
ArrayList<String> proxyList = getProxy("https://raw.githubusercontent.com/hookzof/socks5_list/master/proxy.txt", TAG);
|
ArrayList<String> proxyList = getProxy("https://raw.githubusercontent.com/hookzof/socks5_list/master/proxy.txt", TAG);
|
||||||
|
|
||||||
if (proxyList == null) {
|
if (proxyList == null) {
|
||||||
@@ -37,7 +38,7 @@ public class Hookzof{
|
|||||||
AndroidUtils.sendToast(getString("proxy_setup_success") + " " + proxy);
|
AndroidUtils.sendToast(getString("proxy_setup_success") + " " + proxy);
|
||||||
RandomProxy.showProxyResult = false;
|
RandomProxy.showProxyResult = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
edit().putString("random_type", "socks").putString("random_host", proxy).commit();
|
edit().putString("random_type", "socks").putString("random_host", proxy).commit();
|
||||||
|
|
||||||
System.setProperty("socksProxyHost", proxy.split(":")[0]);
|
System.setProperty("socksProxyHost", proxy.split(":")[0]);
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
package ru.vtosters.lite.proxy.socks;
|
package ru.vtosters.lite.proxy.socks;
|
||||||
|
|
||||||
import static ru.vtosters.lite.proxy.GithubList.getProxy;
|
import static ru.vtosters.lite.proxy.GithubList.getProxy;
|
||||||
import static ru.vtosters.lite.proxy.ProxyUtils.forceProxyApplying;
|
import static ru.vtosters.lite.proxy.ProxyUtils.forceProxyApplying;
|
||||||
import static ru.vtosters.lite.proxy.ProxyUtils.hasProxy;
|
import static ru.vtosters.lite.proxy.ProxyUtils.hasProxy;
|
||||||
@@ -13,10 +14,10 @@ import java.util.ArrayList;
|
|||||||
import ru.vtosters.lite.proxy.RandomProxy;
|
import ru.vtosters.lite.proxy.RandomProxy;
|
||||||
import ru.vtosters.lite.utils.AndroidUtils;
|
import ru.vtosters.lite.utils.AndroidUtils;
|
||||||
|
|
||||||
public class Jetkai{
|
public class Jetkai {
|
||||||
private static final String TAG = "Jetkai_Socks";
|
private static final String TAG = "Jetkai_Socks";
|
||||||
|
|
||||||
public static void loadProxy() throws IOException{
|
public static void loadProxy() throws IOException {
|
||||||
ArrayList<String> proxyList = getProxy("https://raw.githubusercontent.com/jetkai/proxy-list/main/online-proxies/txt/proxies-socks5.txt", TAG);
|
ArrayList<String> proxyList = getProxy("https://raw.githubusercontent.com/jetkai/proxy-list/main/online-proxies/txt/proxies-socks5.txt", TAG);
|
||||||
|
|
||||||
if (proxyList == null) {
|
if (proxyList == null) {
|
||||||
@@ -37,7 +38,7 @@ public class Jetkai{
|
|||||||
AndroidUtils.sendToast(getString("proxy_setup_success") + " " + proxy);
|
AndroidUtils.sendToast(getString("proxy_setup_success") + " " + proxy);
|
||||||
RandomProxy.showProxyResult = false;
|
RandomProxy.showProxyResult = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
edit().putString("random_type", "socks").putString("random_host", proxy).commit();
|
edit().putString("random_type", "socks").putString("random_host", proxy).commit();
|
||||||
|
|
||||||
System.setProperty("socksProxyHost", proxy.split(":")[0]);
|
System.setProperty("socksProxyHost", proxy.split(":")[0]);
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
package ru.vtosters.lite.proxy.socks;
|
package ru.vtosters.lite.proxy.socks;
|
||||||
|
|
||||||
import static ru.vtosters.lite.proxy.GithubList.getProxy;
|
import static ru.vtosters.lite.proxy.GithubList.getProxy;
|
||||||
import static ru.vtosters.lite.proxy.ProxyUtils.forceProxyApplying;
|
import static ru.vtosters.lite.proxy.ProxyUtils.forceProxyApplying;
|
||||||
import static ru.vtosters.lite.proxy.ProxyUtils.hasProxy;
|
import static ru.vtosters.lite.proxy.ProxyUtils.hasProxy;
|
||||||
@@ -13,10 +14,10 @@ import java.util.ArrayList;
|
|||||||
import ru.vtosters.lite.proxy.RandomProxy;
|
import ru.vtosters.lite.proxy.RandomProxy;
|
||||||
import ru.vtosters.lite.utils.AndroidUtils;
|
import ru.vtosters.lite.utils.AndroidUtils;
|
||||||
|
|
||||||
public class Roosterkid{
|
public class Roosterkid {
|
||||||
private static final String TAG = "Roosterkid_Socks";
|
private static final String TAG = "Roosterkid_Socks";
|
||||||
|
|
||||||
public static void loadProxy() throws IOException{
|
public static void loadProxy() throws IOException {
|
||||||
ArrayList<String> proxyList = getProxy("https://raw.githubusercontent.com/roosterkid/openproxylist/main/SOCKS5_RAW.txt", TAG);
|
ArrayList<String> proxyList = getProxy("https://raw.githubusercontent.com/roosterkid/openproxylist/main/SOCKS5_RAW.txt", TAG);
|
||||||
|
|
||||||
if (proxyList == null) {
|
if (proxyList == null) {
|
||||||
@@ -37,7 +38,7 @@ public class Roosterkid{
|
|||||||
AndroidUtils.sendToast(getString("proxy_setup_success") + " " + proxy);
|
AndroidUtils.sendToast(getString("proxy_setup_success") + " " + proxy);
|
||||||
RandomProxy.showProxyResult = false;
|
RandomProxy.showProxyResult = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
edit().putString("random_type", "socks").putString("random_host", proxy).commit();
|
edit().putString("random_type", "socks").putString("random_host", proxy).commit();
|
||||||
|
|
||||||
System.setProperty("socksProxyHost", proxy.split(":")[0]);
|
System.setProperty("socksProxyHost", proxy.split(":")[0]);
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
package ru.vtosters.lite.proxy.socks;
|
package ru.vtosters.lite.proxy.socks;
|
||||||
|
|
||||||
import static ru.vtosters.lite.proxy.GithubList.getProxy;
|
import static ru.vtosters.lite.proxy.GithubList.getProxy;
|
||||||
import static ru.vtosters.lite.proxy.ProxyUtils.forceProxyApplying;
|
import static ru.vtosters.lite.proxy.ProxyUtils.forceProxyApplying;
|
||||||
import static ru.vtosters.lite.proxy.ProxyUtils.hasProxy;
|
import static ru.vtosters.lite.proxy.ProxyUtils.hasProxy;
|
||||||
@@ -13,10 +14,10 @@ import java.util.ArrayList;
|
|||||||
import ru.vtosters.lite.proxy.RandomProxy;
|
import ru.vtosters.lite.proxy.RandomProxy;
|
||||||
import ru.vtosters.lite.utils.AndroidUtils;
|
import ru.vtosters.lite.utils.AndroidUtils;
|
||||||
|
|
||||||
public class TheSpeedX{
|
public class TheSpeedX {
|
||||||
private static final String TAG = "TheSpeedX_Socks";
|
private static final String TAG = "TheSpeedX_Socks";
|
||||||
|
|
||||||
public static void loadProxy() throws IOException{
|
public static void loadProxy() throws IOException {
|
||||||
ArrayList<String> proxyList = getProxy("https://raw.githubusercontent.com/TheSpeedX/PROXY-List/master/socks5.txt", TAG);
|
ArrayList<String> proxyList = getProxy("https://raw.githubusercontent.com/TheSpeedX/PROXY-List/master/socks5.txt", TAG);
|
||||||
|
|
||||||
if (proxyList == null) {
|
if (proxyList == null) {
|
||||||
@@ -37,7 +38,7 @@ public class TheSpeedX{
|
|||||||
AndroidUtils.sendToast(getString("proxy_setup_success") + " " + proxy);
|
AndroidUtils.sendToast(getString("proxy_setup_success") + " " + proxy);
|
||||||
RandomProxy.showProxyResult = false;
|
RandomProxy.showProxyResult = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
edit().putString("random_type", "socks").putString("random_host", proxy).commit();
|
edit().putString("random_type", "socks").putString("random_host", proxy).commit();
|
||||||
|
|
||||||
System.setProperty("socksProxyHost", proxy.split(":")[0]);
|
System.setProperty("socksProxyHost", proxy.split(":")[0]);
|
||||||
|
|||||||
@@ -1,8 +1,9 @@
|
|||||||
package ru.vtosters.lite.proxy.socks;
|
package ru.vtosters.lite.proxy.socks;
|
||||||
|
|
||||||
import static ru.vtosters.lite.proxy.ProxyUtils.forceProxyApplying;
|
import static ru.vtosters.lite.proxy.ProxyUtils.forceProxyApplying;
|
||||||
|
|
||||||
public class Zaborona{
|
public class Zaborona {
|
||||||
public static void loadProxy(){
|
public static void loadProxy() {
|
||||||
System.setProperty("socksProxyHost", "socks.zaboronahelp.pp.ua");
|
System.setProperty("socksProxyHost", "socks.zaboronahelp.pp.ua");
|
||||||
System.setProperty("socksProxyPort", "1488");
|
System.setProperty("socksProxyPort", "1488");
|
||||||
forceProxyApplying();
|
forceProxyApplying();
|
||||||
|
|||||||
@@ -11,24 +11,10 @@ import ru.vtosters.lite.utils.AndroidUtils;
|
|||||||
|
|
||||||
public abstract class BaseTranslator {
|
public abstract class BaseTranslator {
|
||||||
|
|
||||||
private final LruCache<String, String> cache = new LruCache<>(200);
|
|
||||||
|
|
||||||
private static final int YANDEX = 0;
|
private static final int YANDEX = 0;
|
||||||
private static final int GOOGLE = 1;
|
private static final int GOOGLE = 1;
|
||||||
private static final int DEEPL = 2;
|
private static final int DEEPL = 2;
|
||||||
|
private final LruCache<String, String> cache = new LruCache<>(200);
|
||||||
@NonNull
|
|
||||||
public abstract String translate(String text, String tl);
|
|
||||||
|
|
||||||
@NonNull
|
|
||||||
public final String getTranslation(String text) {
|
|
||||||
var val = cache.get(text);
|
|
||||||
if (val != null)
|
|
||||||
return val;
|
|
||||||
var translation = translate(text, getToLanguage());
|
|
||||||
cache.put(text, translation);
|
|
||||||
return translation;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static String getToLanguage() {
|
public static String getToLanguage() {
|
||||||
var lang = preferences.getString("lang_target", "system");
|
var lang = preferences.getString("lang_target", "system");
|
||||||
@@ -51,4 +37,17 @@ public abstract class BaseTranslator {
|
|||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
public abstract String translate(String text, String tl);
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
public final String getTranslation(String text) {
|
||||||
|
var val = cache.get(text);
|
||||||
|
if (val != null)
|
||||||
|
return val;
|
||||||
|
var translation = translate(text, getToLanguage());
|
||||||
|
cache.put(text, translation);
|
||||||
|
return translation;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -54,6 +54,11 @@ public class DeepLTranslator extends BaseTranslator {
|
|||||||
return instance;
|
return instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static Long getTimestamp(int iNumber) {
|
||||||
|
var now = System.currentTimeMillis();
|
||||||
|
return Long.valueOf((((long) iNumber) + now) - (now % ((long) iNumber)));
|
||||||
|
}
|
||||||
|
|
||||||
@NonNull
|
@NonNull
|
||||||
@Override
|
@Override
|
||||||
public String translate(String text, String tl) {
|
public String translate(String text, String tl) {
|
||||||
@@ -126,9 +131,4 @@ public class DeepLTranslator extends BaseTranslator {
|
|||||||
}
|
}
|
||||||
return text;
|
return text;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Long getTimestamp(int iNumber) {
|
|
||||||
var now = System.currentTimeMillis();
|
|
||||||
return Long.valueOf((((long) iNumber) + now) - (now % ((long) iNumber)));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,9 +7,7 @@ import static ru.vtosters.lite.utils.ThemesUtils.getAccentColor;
|
|||||||
import static ru.vtosters.lite.utils.ThemesUtils.getSTextAttr;
|
import static ru.vtosters.lite.utils.ThemesUtils.getSTextAttr;
|
||||||
import static ru.vtosters.lite.utils.ThemesUtils.getTextAttr;
|
import static ru.vtosters.lite.utils.ThemesUtils.getTextAttr;
|
||||||
|
|
||||||
import android.app.AlertDialog;
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.DialogInterface;
|
|
||||||
import android.content.res.ColorStateList;
|
import android.content.res.ColorStateList;
|
||||||
import android.graphics.drawable.Drawable;
|
import android.graphics.drawable.Drawable;
|
||||||
import android.preference.PreferenceManager;
|
import android.preference.PreferenceManager;
|
||||||
@@ -24,6 +22,7 @@ import androidx.preference.ListPreference;
|
|||||||
import androidx.preference.Preference;
|
import androidx.preference.Preference;
|
||||||
import androidx.preference.PreferenceCategory;
|
import androidx.preference.PreferenceCategory;
|
||||||
|
|
||||||
|
import com.vk.core.dialogs.alert.VkAlertDialog;
|
||||||
import com.vtosters.lite.general.fragments.MaterialPreferenceToolbarFragment;
|
import com.vtosters.lite.general.fragments.MaterialPreferenceToolbarFragment;
|
||||||
import com.vtosters.lite.ui.MaterialSwitchPreference;
|
import com.vtosters.lite.ui.MaterialSwitchPreference;
|
||||||
|
|
||||||
@@ -178,23 +177,20 @@ public class PreferencesUtil {
|
|||||||
margin.setMargins(dp2px(20f), 0, dp2px(20f), 0);
|
margin.setMargins(dp2px(20f), 0, dp2px(20f), 0);
|
||||||
editText.setLayoutParams(margin);
|
editText.setLayoutParams(margin);
|
||||||
|
|
||||||
AlertDialog.Builder builder = new AlertDialog.Builder(fragment.getContext());
|
new VkAlertDialog.Builder(fragment.getContext())
|
||||||
builder.setTitle(title);
|
.setTitle(title)
|
||||||
builder.setView(linearLayout);
|
.setView(linearLayout)
|
||||||
builder.setPositiveButton("OK", (dialog, which) -> {
|
.setPositiveButton("OK", (dialog, which) -> {
|
||||||
boolean change = editTextPrefChangeListener.onChanged(preference, editText.getText().toString());
|
boolean change = editTextPrefChangeListener.onChanged(preference, editText.getText().toString());
|
||||||
if (!change)
|
if (!change)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
PreferenceManager.getDefaultSharedPreferences(getGlobalContext())
|
PreferenceManager.getDefaultSharedPreferences(getGlobalContext())
|
||||||
.edit()
|
.edit()
|
||||||
.putString(key, editText.getText().toString())
|
.putString(key, editText.getText().toString())
|
||||||
.apply();
|
.apply();
|
||||||
});
|
})
|
||||||
|
.show();
|
||||||
var alert = builder.create();
|
|
||||||
alert.show();
|
|
||||||
alert.getButton(DialogInterface.BUTTON_POSITIVE).setTextColor(getAccentColor());
|
|
||||||
return false;
|
return false;
|
||||||
}); // preference.setOnPreferenceClickListener(listener)
|
}); // preference.setOnPreferenceClickListener(listener)
|
||||||
|
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ import ru.vtosters.lite.utils.LayoutUtils;
|
|||||||
|
|
||||||
public class VKAdminTokenActivity extends AppCompatActivity {
|
public class VKAdminTokenActivity extends AppCompatActivity {
|
||||||
|
|
||||||
private static final String URL = "https://" + getOauth() +"/authorize?client_id=6121396&scope=1073737727&redirect_uri=https://oauth.vk.com/blank.html&display=page&response_type=token&revoke=1";
|
private static final String URL = "https://" + getOauth() + "/authorize?client_id=6121396&scope=1073737727&redirect_uri=https://oauth.vk.com/blank.html&display=page&response_type=token&revoke=1";
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onCreate(@Nullable Bundle bundle) {
|
protected void onCreate(@Nullable Bundle bundle) {
|
||||||
|
|||||||
@@ -218,6 +218,10 @@ public class CategorizedAdapter extends RecyclerView.Adapter<CategorizedAdapter.
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public interface IViewHolderBinder {
|
||||||
|
void bind(CategorizedViewHolder holder, int pos);
|
||||||
|
}
|
||||||
|
|
||||||
public static class CategorizedViewHolder extends RecyclerView.ViewHolder {
|
public static class CategorizedViewHolder extends RecyclerView.ViewHolder {
|
||||||
|
|
||||||
private final LinearLayout mMovingItemContainer;
|
private final LinearLayout mMovingItemContainer;
|
||||||
@@ -262,8 +266,4 @@ public class CategorizedAdapter extends RecyclerView.Adapter<CategorizedAdapter.
|
|||||||
mMovingItemContainer.setVisibility(View.INVISIBLE);
|
mMovingItemContainer.setVisibility(View.INVISIBLE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public interface IViewHolderBinder {
|
|
||||||
void bind(CategorizedViewHolder holder, int pos);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ package ru.vtosters.lite.ui.adapters;
|
|||||||
import static ru.vtosters.lite.utils.ThemesUtils.getTextAttr;
|
import static ru.vtosters.lite.utils.ThemesUtils.getTextAttr;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
import android.content.res.ColorStateList;
|
||||||
import android.graphics.drawable.Drawable;
|
import android.graphics.drawable.Drawable;
|
||||||
import android.view.Gravity;
|
import android.view.Gravity;
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
@@ -15,28 +16,27 @@ import android.widget.LinearLayout;
|
|||||||
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
|
import androidx.core.widget.TextViewCompat;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import ru.vtosters.lite.utils.AndroidUtils;
|
import ru.vtosters.lite.utils.AndroidUtils;
|
||||||
import ru.vtosters.lite.utils.LayoutUtils;
|
import ru.vtosters.lite.utils.LayoutUtils;
|
||||||
|
import ru.vtosters.lite.utils.ThemesUtils;
|
||||||
|
|
||||||
public class ImagineArrayAdapter extends ArrayAdapter<ImagineArrayAdapter.ImagineArrayAdapterItem> {
|
public class ImagineArrayAdapter extends ArrayAdapter<ImagineArrayAdapter.ImagineArrayAdapterItem> {
|
||||||
|
|
||||||
private List<ImagineArrayAdapterItem> mItems = new ArrayList<>();
|
private List<ImagineArrayAdapterItem> mItems = new ArrayList<>();
|
||||||
private final OnClickListener mListener;
|
|
||||||
private int mSelectedIndex = -1;
|
private int mSelectedIndex = -1;
|
||||||
|
|
||||||
public ImagineArrayAdapter(@NonNull Context context, OnClickListener listener) {
|
public ImagineArrayAdapter(@NonNull Context context) {
|
||||||
super(context, 0);
|
super(context, 0);
|
||||||
this.mListener = listener;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public ImagineArrayAdapter(@NonNull Context context, List<ImagineArrayAdapterItem> items, OnClickListener listener) {
|
public ImagineArrayAdapter(@NonNull Context context, List<ImagineArrayAdapterItem> items) {
|
||||||
super(context, 0, items);
|
super(context, 0, items);
|
||||||
mItems = items;
|
mItems = items;
|
||||||
this.mListener = listener;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setSelected(int i) {
|
public void setSelected(int i) {
|
||||||
@@ -89,33 +89,26 @@ public class ImagineArrayAdapter extends ArrayAdapter<ImagineArrayAdapter.Imagin
|
|||||||
container.setGravity(Gravity.CENTER_VERTICAL);
|
container.setGravity(Gravity.CENTER_VERTICAL);
|
||||||
container.setPadding(0, AndroidUtils.dp2px(5.0f), 0, AndroidUtils.dp2px(5.0f));
|
container.setPadding(0, AndroidUtils.dp2px(5.0f), 0, AndroidUtils.dp2px(5.0f));
|
||||||
container.setLayoutParams(new ViewGroup.LayoutParams(-1, -2));
|
container.setLayoutParams(new ViewGroup.LayoutParams(-1, -2));
|
||||||
container.setOnClickListener(v -> {
|
|
||||||
if (position != mSelectedIndex) {
|
|
||||||
mListener.onClick(position);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// if make radiobutton without layout inflation it can't be unclickable
|
// if make radiobutton without layout inflation it can't be unclickable
|
||||||
var checkedTextView = (CheckedTextView) LayoutInflater.from(getContext())
|
var checkedTextView = (CheckedTextView) LayoutInflater.from(getContext())
|
||||||
.inflate(AndroidUtils.getIdentifier("select_dialog_singlechoice_material", "layout"), parent, false);
|
.inflate(AndroidUtils.getIdentifier("select_dialog_singlechoice_material", "layout"), parent, false);
|
||||||
|
// for amoled
|
||||||
|
var tintList = new ColorStateList(
|
||||||
|
new int[][] { new int[] { android.R.attr.state_checked }, new int[] { -android.R.attr.state_checked }},
|
||||||
|
new int[] { ThemesUtils.getAccentColor(), ThemesUtils.getSTextAttr() });
|
||||||
|
TextViewCompat.setCompoundDrawableTintList(checkedTextView, tintList);
|
||||||
checkedTextView.setChecked(position == mSelectedIndex);
|
checkedTextView.setChecked(position == mSelectedIndex);
|
||||||
container.addView(checkedTextView, LayoutUtils.createLinear(AndroidUtils.dp2px(50.0f), -2));
|
container.addView(checkedTextView, LayoutUtils.createLinear(AndroidUtils.dp2px(50.0f), -2));
|
||||||
|
|
||||||
var item = mItems.get(position);
|
var item = mItems.get(position);
|
||||||
|
|
||||||
var imageView = new ImageView(getContext());
|
var icon = new ImageView(getContext());
|
||||||
imageView.setImageDrawable(item.getIcon());
|
icon.setImageDrawable(item.getIcon());
|
||||||
imageView.setPadding(
|
icon.setScaleType(ImageView.ScaleType.FIT_CENTER);
|
||||||
AndroidUtils.dp2px(13.0f),
|
var iconParams = LayoutUtils.createLinear(AndroidUtils.dp2px(35.0f), AndroidUtils.dp2px(35.0f));
|
||||||
0,
|
iconParams.leftMargin = AndroidUtils.dp2px(10);
|
||||||
0,
|
container.addView(icon, iconParams);
|
||||||
0
|
|
||||||
);
|
|
||||||
var imageViewParams = LayoutUtils.createLinear(
|
|
||||||
AndroidUtils.dp2px(50.0f),
|
|
||||||
AndroidUtils.dp2px(50.0f)
|
|
||||||
);
|
|
||||||
container.addView(imageView, imageViewParams);
|
|
||||||
|
|
||||||
var textView = new CheckedTextView(getContext());
|
var textView = new CheckedTextView(getContext());
|
||||||
textView.setText(item.getText());
|
textView.setText(item.getText());
|
||||||
@@ -165,8 +158,4 @@ public class ImagineArrayAdapter extends ArrayAdapter<ImagineArrayAdapter.Imagin
|
|||||||
return mText;
|
return mText;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public interface OnClickListener {
|
|
||||||
void onClick(int i);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,6 +25,12 @@ public class MessagesPreviewAdapter extends RecyclerView.Adapter<MessagesPreview
|
|||||||
|
|
||||||
private final String[] mMessages = AndroidUtils.getArray("wallpaper_change_dialog");
|
private final String[] mMessages = AndroidUtils.getArray("wallpaper_change_dialog");
|
||||||
|
|
||||||
|
private static int getColorFromAttribute(Context context, int attrId) {
|
||||||
|
TypedValue typedValue = new TypedValue();
|
||||||
|
context.getTheme().resolveAttribute(attrId, typedValue, true);
|
||||||
|
return typedValue.data;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getItemViewType(int i) {
|
public int getItemViewType(int i) {
|
||||||
return i % 2 == 0 ? ANONYMOUS : ME;
|
return i % 2 == 0 ? ANONYMOUS : ME;
|
||||||
@@ -70,12 +76,6 @@ public class MessagesPreviewAdapter extends RecyclerView.Adapter<MessagesPreview
|
|||||||
return mMessages.length;
|
return mMessages.length;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static int getColorFromAttribute(Context context, int attrId) {
|
|
||||||
TypedValue typedValue = new TypedValue();
|
|
||||||
context.getTheme().resolveAttribute(attrId, typedValue, true);
|
|
||||||
return typedValue.data;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected static class MessagePreviewViewHolder extends RecyclerView.ViewHolder {
|
protected static class MessagePreviewViewHolder extends RecyclerView.ViewHolder {
|
||||||
|
|
||||||
private final TextView mMessage;
|
private final TextView mMessage;
|
||||||
|
|||||||
@@ -24,7 +24,6 @@ import com.aefyr.tsg.g2.TelegramStickersPack;
|
|||||||
import com.aefyr.tsg.g2.TelegramStickersService;
|
import com.aefyr.tsg.g2.TelegramStickersService;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.util.Collections;
|
|
||||||
|
|
||||||
import ru.vtosters.lite.tgs.TGPref;
|
import ru.vtosters.lite.tgs.TGPref;
|
||||||
import ru.vtosters.lite.ui.components.IItemMovingListener;
|
import ru.vtosters.lite.ui.components.IItemMovingListener;
|
||||||
|
|||||||
@@ -37,8 +37,10 @@ public class CrashReporter {
|
|||||||
Thread.setDefaultUncaughtExceptionHandler((thread, th) -> CrashReporter.start(defaultUncaughtExceptionHandler, thread, th, activity));
|
Thread.setDefaultUncaughtExceptionHandler((thread, th) -> CrashReporter.start(defaultUncaughtExceptionHandler, thread, th, activity));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SuppressLint("UnspecifiedImmutableFlag")
|
||||||
static void start(Thread.UncaughtExceptionHandler uncaughtExceptionHandler, Thread thread, Throwable th, Activity activity) {
|
static void start(Thread.UncaughtExceptionHandler uncaughtExceptionHandler, Thread thread, Throwable th, Activity activity) {
|
||||||
logString = getStackTrace(th) + "\n\n" + new DeviceInfoCollector().collect(getGlobalContext()).toDeviceName() + ", commit: " + getBuildNumber();
|
logString = getStackTrace(th) + "\n\n" + new DeviceInfoCollector().collect().toDeviceName();
|
||||||
|
|
||||||
if (Build.VERSION.SDK_INT >= 26) {
|
if (Build.VERSION.SDK_INT >= 26) {
|
||||||
var notificationChannel = new NotificationChannel("crashes", "crash", NotificationManager.IMPORTANCE_DEFAULT);
|
var notificationChannel = new NotificationChannel("crashes", "crash", NotificationManager.IMPORTANCE_DEFAULT);
|
||||||
notificationChannel.enableVibration(true);
|
notificationChannel.enableVibration(true);
|
||||||
@@ -58,6 +60,7 @@ public class CrashReporter {
|
|||||||
var saveLogIntent = new Intent(getGlobalContext(), LogWriterService.class);
|
var saveLogIntent = new Intent(getGlobalContext(), LogWriterService.class);
|
||||||
saveLogIntent.putExtra("log", logString);
|
saveLogIntent.putExtra("log", logString);
|
||||||
saveLogIntent.putExtra("notificationId", 1);
|
saveLogIntent.putExtra("notificationId", 1);
|
||||||
|
|
||||||
@SuppressLint("UnspecifiedImmutableFlag")
|
@SuppressLint("UnspecifiedImmutableFlag")
|
||||||
var psaveLogIntent = PendingIntent.getService(getGlobalContext(), 0, saveLogIntent, PendingIntent.FLAG_CANCEL_CURRENT);
|
var psaveLogIntent = PendingIntent.getService(getGlobalContext(), 0, saveLogIntent, PendingIntent.FLAG_CANCEL_CURRENT);
|
||||||
|
|
||||||
@@ -74,9 +77,8 @@ public class CrashReporter {
|
|||||||
builder.setChannelId("crashes");
|
builder.setChannelId("crashes");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
((NotificationManager) getGlobalContext().getSystemService(Context.NOTIFICATION_SERVICE)).notify(-2147483548, builder.build());
|
((NotificationManager) getGlobalContext().getSystemService(Context.NOTIFICATION_SERVICE)).notify(-2147483548, builder.build());
|
||||||
Log.e("VTosters Lite", "crashed: " + th.getLocalizedMessage());
|
Log.e("VTLite", "crashed: " + th.getLocalizedMessage());
|
||||||
uncaughtExceptionHandler.uncaughtException(thread, th);
|
uncaughtExceptionHandler.uncaughtException(thread, th);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ package ru.vtosters.lite.ui.components;
|
|||||||
|
|
||||||
import static ru.vtosters.lite.utils.AndroidUtils.getGlobalContext;
|
import static ru.vtosters.lite.utils.AndroidUtils.getGlobalContext;
|
||||||
import static ru.vtosters.lite.utils.AndroidUtils.getPreferences;
|
import static ru.vtosters.lite.utils.AndroidUtils.getPreferences;
|
||||||
import static ru.vtosters.lite.utils.Preferences.getBoolValue;
|
|
||||||
import static ru.vtosters.lite.utils.Preferences.milkshake;
|
import static ru.vtosters.lite.utils.Preferences.milkshake;
|
||||||
import static ru.vtosters.lite.utils.Preferences.superapp;
|
import static ru.vtosters.lite.utils.Preferences.superapp;
|
||||||
import static ru.vtosters.lite.utils.Preferences.useNewSettings;
|
import static ru.vtosters.lite.utils.Preferences.useNewSettings;
|
||||||
@@ -33,7 +32,6 @@ import com.vtosters.lite.fragments.p2.DocumentsViewFragment;
|
|||||||
import com.vtosters.lite.fragments.s2.GroupsFragment1;
|
import com.vtosters.lite.fragments.s2.GroupsFragment1;
|
||||||
import com.vtosters.lite.fragments.t2.c.DialogsFragment;
|
import com.vtosters.lite.fragments.t2.c.DialogsFragment;
|
||||||
import com.vtosters.lite.fragments.y2.VideoCatalogFragment;
|
import com.vtosters.lite.fragments.y2.VideoCatalogFragment;
|
||||||
import com.vtosters.lite.fragments.y2.VideosFragment;
|
|
||||||
import com.vtosters.lite.general.fragments.GamesFragment;
|
import com.vtosters.lite.general.fragments.GamesFragment;
|
||||||
import com.vtosters.lite.general.fragments.PhotosFragment;
|
import com.vtosters.lite.general.fragments.PhotosFragment;
|
||||||
|
|
||||||
@@ -49,11 +47,13 @@ import ru.vtosters.lite.utils.AndroidUtils;
|
|||||||
public class DockBarEditorManager {
|
public class DockBarEditorManager {
|
||||||
public static final int MIN_SELECTED_TABS = 3;
|
public static final int MIN_SELECTED_TABS = 3;
|
||||||
public static final int MAX_SELECTED_TABS = 9;
|
public static final int MAX_SELECTED_TABS = 9;
|
||||||
|
private static DockBarEditorManager sInstance;
|
||||||
private final List<DockBarTab> mSelectedTabs = new ArrayList<>();
|
private final List<DockBarTab> mSelectedTabs = new ArrayList<>();
|
||||||
private final List<DockBarTab> mDisabledTabs = new ArrayList<>();
|
private final List<DockBarTab> mDisabledTabs = new ArrayList<>();
|
||||||
|
|
||||||
private static DockBarEditorManager sInstance;
|
public DockBarEditorManager() {
|
||||||
|
init();
|
||||||
|
}
|
||||||
|
|
||||||
public static DockBarEditorManager getInstance() {
|
public static DockBarEditorManager getInstance() {
|
||||||
return sInstance == null
|
return sInstance == null
|
||||||
@@ -61,10 +61,6 @@ public class DockBarEditorManager {
|
|||||||
: sInstance;
|
: sInstance;
|
||||||
}
|
}
|
||||||
|
|
||||||
public DockBarEditorManager() {
|
|
||||||
init();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void init() {
|
private void init() {
|
||||||
if (vkme()) {
|
if (vkme()) {
|
||||||
mSelectedTabs.add(getTabByTag("tab_settings"));
|
mSelectedTabs.add(getTabByTag("tab_settings"));
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ public class StickerTouchHelperCallback extends ItemTouchHelper.Callback {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getMovementFlags(@NonNull RecyclerView recyclerView, @NonNull RecyclerView.ViewHolder viewHolder) {
|
public int getMovementFlags(@NonNull RecyclerView recyclerView, @NonNull RecyclerView.ViewHolder viewHolder) {
|
||||||
int dragFlags = ItemTouchHelper.UP | ItemTouchHelper.DOWN |
|
int dragFlags = ItemTouchHelper.UP | ItemTouchHelper.DOWN |
|
||||||
ItemTouchHelper.LEFT | ItemTouchHelper.RIGHT;
|
ItemTouchHelper.LEFT | ItemTouchHelper.RIGHT;
|
||||||
|
|
||||||
int swipeFlags = ItemTouchHelper.START | ItemTouchHelper.END;
|
int swipeFlags = ItemTouchHelper.START | ItemTouchHelper.END;
|
||||||
|
|||||||
@@ -14,10 +14,13 @@ import ru.vtosters.lite.utils.AndroidUtils;
|
|||||||
|
|
||||||
public class SuperAppEditorManager {
|
public class SuperAppEditorManager {
|
||||||
|
|
||||||
|
private static SuperAppEditorManager sInstance;
|
||||||
private final List<SuperAppItem> mSelectedItems = new ArrayList<>();
|
private final List<SuperAppItem> mSelectedItems = new ArrayList<>();
|
||||||
private final List<SuperAppItem> mDisabledItems = new ArrayList<>();
|
private final List<SuperAppItem> mDisabledItems = new ArrayList<>();
|
||||||
|
|
||||||
private static SuperAppEditorManager sInstance;
|
public SuperAppEditorManager() {
|
||||||
|
init();
|
||||||
|
}
|
||||||
|
|
||||||
public static SuperAppEditorManager getInstance() {
|
public static SuperAppEditorManager getInstance() {
|
||||||
return sInstance == null
|
return sInstance == null
|
||||||
@@ -25,10 +28,6 @@ public class SuperAppEditorManager {
|
|||||||
: sInstance;
|
: sInstance;
|
||||||
}
|
}
|
||||||
|
|
||||||
public SuperAppEditorManager() {
|
|
||||||
init();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void init() {
|
private void init() {
|
||||||
var tmp = getPreferences().getString("superapp_items", "menu,miniapps,vkpay_slim,greeting,promo,holiday,weather,sport,games,informer,food,event,music,vk_run");
|
var tmp = getPreferences().getString("superapp_items", "menu,miniapps,vkpay_slim,greeting,promo,holiday,weather,sport,games,informer,food,event,music,vk_run");
|
||||||
var selectedTags = !tmp.isEmpty() ? tmp.split(",") : new String[0];
|
var selectedTags = !tmp.isEmpty() ? tmp.split(",") : new String[0];
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ import android.content.Intent;
|
|||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
import android.os.PowerManager;
|
import android.os.PowerManager;
|
||||||
|
import android.provider.Settings;
|
||||||
|
|
||||||
import com.vk.core.dialogs.alert.VkAlertDialog;
|
import com.vk.core.dialogs.alert.VkAlertDialog;
|
||||||
|
|
||||||
@@ -21,22 +22,19 @@ public class DisableBattery {
|
|||||||
if (OEMDetector.isOEM() && Build.VERSION.SDK_INT >= 23 && getBoolValue("showDoze", true)) {
|
if (OEMDetector.isOEM() && Build.VERSION.SDK_INT >= 23 && getBoolValue("showDoze", true)) {
|
||||||
final Context context = getGlobalContext();
|
final Context context = getGlobalContext();
|
||||||
if (!((PowerManager) context.getSystemService(Context.POWER_SERVICE)).isIgnoringBatteryOptimizations(context.getPackageName())) {
|
if (!((PowerManager) context.getSystemService(Context.POWER_SERVICE)).isIgnoringBatteryOptimizations(context.getPackageName())) {
|
||||||
VkAlertDialog.Builder builder = new VkAlertDialog.Builder(activity);
|
new VkAlertDialog.Builder(activity)
|
||||||
builder.setTitle(getString("batteryissuetitle"));
|
.setTitle(getString("batteryissuetitle"))
|
||||||
builder.setMessage(getString("batteryissuesumm"));
|
.setMessage(getString("batteryissuesumm"))
|
||||||
builder.setCancelable(false);
|
.setCancelable(false)
|
||||||
// android.content.DialogInterface.OnClickListener
|
.setPositiveButton(getString("batteryissuebtn1"), (dialogInterface, i) -> {
|
||||||
builder.setPositiveButton(getString("batteryissuebtn1"), (dialogInterface, i) -> {
|
var intent = new Intent(Settings.ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS)
|
||||||
Intent intent = new Intent("android.settings.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS");
|
.setData(Uri.parse("package:" + context.getPackageName()));
|
||||||
StringBuilder sb = new StringBuilder();
|
context.startActivity(intent);
|
||||||
sb.append("package:");
|
})
|
||||||
sb.append(context.getPackageName());
|
.setNeutralButton(getString("batteryissuebtn2"),
|
||||||
intent.setData(Uri.parse(sb.toString()));
|
(dialogInterface, i) -> edit().putBoolean("showDoze", false).apply()
|
||||||
context.startActivity(intent);
|
)
|
||||||
});
|
.show();
|
||||||
// android.content.DialogInterface.OnClickListener
|
|
||||||
builder.setNeutralButton(getString("batteryissuebtn2"), (dialogInterface, i) -> edit().putBoolean("showDoze", false).apply());
|
|
||||||
builder.show();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,7 +7,6 @@ import static ru.vtosters.lite.utils.GmsUtils.isGmsInstalled;
|
|||||||
import static ru.vtosters.lite.utils.Preferences.getBoolValue;
|
import static ru.vtosters.lite.utils.Preferences.getBoolValue;
|
||||||
|
|
||||||
import android.app.Activity;
|
import android.app.Activity;
|
||||||
import android.content.Context;
|
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
|
|
||||||
import com.vk.core.dialogs.alert.VkAlertDialog;
|
import com.vk.core.dialogs.alert.VkAlertDialog;
|
||||||
@@ -17,22 +16,23 @@ import ru.vtosters.lite.ui.fragments.InstallGMSFragment;
|
|||||||
|
|
||||||
public class InstallGMS {
|
public class InstallGMS {
|
||||||
public static void alert(final Activity activity) {
|
public static void alert(final Activity activity) {
|
||||||
if (!isGmsInstalled()) {
|
if (!isGmsInstalled() && getBoolValue("showAlertGms", true)) {
|
||||||
VkAlertDialog.Builder builder = new VkAlertDialog.Builder(activity);
|
new VkAlertDialog.Builder(activity)
|
||||||
builder.setTitle(getString("warning"));
|
.setTitle(getString("warning"))
|
||||||
builder.setMessage(getString("gmsissuesumm"));
|
.setMessage(getString("gmsissuesumm"))
|
||||||
builder.setCancelable(false);
|
.setCancelable(false)
|
||||||
builder.setPositiveButton(getString("gmsissuebtn1"), (dialogInterface, i) -> edit().putBoolean("showAlertGms", false).apply());
|
.setPositiveButton(getString("gmsissuebtn1"), (
|
||||||
builder.setNeutralButton(getString("gmsissuebtn2"), (dialogInterface, i) -> {
|
dialogInterface, i) -> edit().putBoolean("showAlertGms", false).apply()
|
||||||
edit().putBoolean("showAlertGms", false).apply();
|
)
|
||||||
Context context = getGlobalContext();
|
.setNeutralButton(getString("gmsissuebtn2"), (dialogInterface, i) -> {
|
||||||
Intent a2 = new Navigator(InstallGMSFragment.class).b(context);
|
edit().putBoolean("showAlertGms", false).apply();
|
||||||
a2.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
var context = getGlobalContext();
|
||||||
context.startActivity(a2);
|
var intent = new Navigator(InstallGMSFragment.class)
|
||||||
});
|
.b(context)
|
||||||
if (getBoolValue("showAlertGms", true)) {
|
.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||||
builder.show();
|
context.startActivity(intent);
|
||||||
}
|
})
|
||||||
|
.show();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ import androidx.appcompat.view.ContextThemeWrapper;
|
|||||||
import androidx.appcompat.widget.SwitchCompat;
|
import androidx.appcompat.widget.SwitchCompat;
|
||||||
|
|
||||||
import com.vk.core.dialogs.alert.VkAlertDialog;
|
import com.vk.core.dialogs.alert.VkAlertDialog;
|
||||||
|
import com.vtosters.lite.R;
|
||||||
|
|
||||||
import ru.vtosters.lite.utils.AndroidUtils;
|
import ru.vtosters.lite.utils.AndroidUtils;
|
||||||
import ru.vtosters.lite.utils.LayoutUtils;
|
import ru.vtosters.lite.utils.LayoutUtils;
|
||||||
@@ -30,12 +31,12 @@ public class MessageSettings {
|
|||||||
rg.setOrientation(LinearLayout.VERTICAL);
|
rg.setOrientation(LinearLayout.VERTICAL);
|
||||||
rg.setPadding(dp2px(18f), dp2px(12f), dp2px(18f), 0);
|
rg.setPadding(dp2px(18f), dp2px(12f), dp2px(18f), 0);
|
||||||
|
|
||||||
RadioButton zero = new RadioButton(new ContextThemeWrapper(context, com.vtosters.lite.R.style.Widget_AppCompat_CompoundButton_RadioButton));
|
RadioButton zero = new RadioButton(new ContextThemeWrapper(context, R.style.Widget_AppCompat_CompoundButton_RadioButton));
|
||||||
RadioButton one = new RadioButton(new ContextThemeWrapper(context, com.vtosters.lite.R.style.Widget_AppCompat_CompoundButton_RadioButton));
|
RadioButton one = new RadioButton(new ContextThemeWrapper(context, R.style.Widget_AppCompat_CompoundButton_RadioButton));
|
||||||
RadioButton two = new RadioButton(new ContextThemeWrapper(context, com.vtosters.lite.R.style.Widget_AppCompat_CompoundButton_RadioButton));
|
RadioButton two = new RadioButton(new ContextThemeWrapper(context, R.style.Widget_AppCompat_CompoundButton_RadioButton));
|
||||||
RadioButton three = new RadioButton(new ContextThemeWrapper(context, com.vtosters.lite.R.style.Widget_AppCompat_CompoundButton_RadioButton));
|
RadioButton three = new RadioButton(new ContextThemeWrapper(context, R.style.Widget_AppCompat_CompoundButton_RadioButton));
|
||||||
RadioButton four = new RadioButton(new ContextThemeWrapper(context, com.vtosters.lite.R.style.Widget_AppCompat_CompoundButton_RadioButton));
|
RadioButton four = new RadioButton(new ContextThemeWrapper(context, R.style.Widget_AppCompat_CompoundButton_RadioButton));
|
||||||
RadioButton five = new RadioButton(new ContextThemeWrapper(context, com.vtosters.lite.R.style.Widget_AppCompat_CompoundButton_RadioButton));
|
RadioButton five = new RadioButton(new ContextThemeWrapper(context, R.style.Widget_AppCompat_CompoundButton_RadioButton));
|
||||||
|
|
||||||
rg.addView(zero);
|
rg.addView(zero);
|
||||||
rg.addView(one);
|
rg.addView(one);
|
||||||
@@ -87,7 +88,7 @@ public class MessageSettings {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@SuppressLint("UseSwitchCompatOrMaterialCode")
|
@SuppressLint("UseSwitchCompatOrMaterialCode")
|
||||||
var silentSwitch = new SwitchCompat(new ContextThemeWrapper(context, com.vtosters.lite.R.style.Widget_AppCompat_CompoundButton_Switch));
|
var silentSwitch = new SwitchCompat(new ContextThemeWrapper(context, R.style.Widget_AppCompat_CompoundButton_Switch));
|
||||||
silentSwitch.setText(AndroidUtils.getString("silent_messages"));
|
silentSwitch.setText(AndroidUtils.getString("silent_messages"));
|
||||||
silentSwitch.setTextSize(TypedValue.COMPLEX_UNIT_PX, dp2px(14f));
|
silentSwitch.setTextSize(TypedValue.COMPLEX_UNIT_PX, dp2px(14f));
|
||||||
silentSwitch.setTextColor(getTextAttr());
|
silentSwitch.setTextColor(getTextAttr());
|
||||||
@@ -104,30 +105,29 @@ public class MessageSettings {
|
|||||||
mContainer.addView(rg, LayoutUtils.createLinear(-1, -2));
|
mContainer.addView(rg, LayoutUtils.createLinear(-1, -2));
|
||||||
mContainer.addView(silentSwitch, LayoutUtils.createLinear(-1, -2));
|
mContainer.addView(silentSwitch, LayoutUtils.createLinear(-1, -2));
|
||||||
|
|
||||||
VkAlertDialog.Builder builder = new VkAlertDialog.Builder(context);
|
new VkAlertDialog.Builder(context)
|
||||||
builder.setTitle(AndroidUtils.getString("message_send_settings_title"));
|
.setTitle(AndroidUtils.getString("message_send_settings_title"))
|
||||||
builder.setMessage(AndroidUtils.getString("silent_messages_time_select"));
|
.setMessage(AndroidUtils.getString("silent_messages_time_select"))
|
||||||
builder.setCancelable(true);
|
.setCancelable(true)
|
||||||
builder.setNegativeButton(AndroidUtils.getString("cancel"), null);
|
.setView(mContainer)
|
||||||
builder.setView(mContainer);
|
.setNegativeButton(AndroidUtils.getString("cancel"), null)
|
||||||
builder.setPositiveButton(AndroidUtils.getString("vtl_confirm"), (dialog, which) -> { // Применить
|
.setPositiveButton(AndroidUtils.getString("vtl_confirm"), (dialog, which) -> { // Применить
|
||||||
var checked = rg.getCheckedRadioButtonId();
|
var checked = rg.getCheckedRadioButtonId();
|
||||||
|
|
||||||
if (checked == zero.getId()) {
|
if (checked == zero.getId()) {
|
||||||
bombCount = "0";
|
bombCount = "0";
|
||||||
} else if (checked == one.getId()) {
|
} else if (checked == one.getId()) {
|
||||||
bombCount = "15s";
|
bombCount = "15s";
|
||||||
} else if (checked == two.getId()) {
|
} else if (checked == two.getId()) {
|
||||||
bombCount = "1m";
|
bombCount = "1m";
|
||||||
} else if (checked == three.getId()) {
|
} else if (checked == three.getId()) {
|
||||||
bombCount = "5m";
|
bombCount = "5m";
|
||||||
} else if (checked == four.getId()) {
|
} else if (checked == four.getId()) {
|
||||||
bombCount = "1h";
|
bombCount = "1h";
|
||||||
} else if (checked == five.getId()) {
|
} else if (checked == five.getId()) {
|
||||||
bombCount = "24h";
|
bombCount = "24h";
|
||||||
}
|
}
|
||||||
});
|
})
|
||||||
|
.show();
|
||||||
builder.show();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
package ru.vtosters.lite.ui.dialogs;
|
package ru.vtosters.lite.ui.dialogs;
|
||||||
|
|
||||||
import static ru.vtosters.lite.utils.AndroidUtils.dp2px;
|
import static ru.vtosters.lite.utils.AndroidUtils.dp2px;
|
||||||
import static ru.vtosters.lite.utils.AndroidUtils.edit;
|
import static ru.vtosters.lite.utils.AndroidUtils.edit;
|
||||||
import static ru.vtosters.lite.utils.AndroidUtils.getPreferences;
|
import static ru.vtosters.lite.utils.AndroidUtils.getPreferences;
|
||||||
@@ -13,7 +14,7 @@ import com.vk.core.dialogs.alert.VkAlertDialog;
|
|||||||
import ru.vtosters.lite.utils.AndroidUtils;
|
import ru.vtosters.lite.utils.AndroidUtils;
|
||||||
import ru.vtosters.lite.utils.LayoutUtils;
|
import ru.vtosters.lite.utils.LayoutUtils;
|
||||||
|
|
||||||
public class RoundingSeekbarDialog{
|
public class RoundingSeekbarDialog {
|
||||||
public static void dialog(Context context) {
|
public static void dialog(Context context) {
|
||||||
LinearLayout mContainer = new LinearLayout(context);
|
LinearLayout mContainer = new LinearLayout(context);
|
||||||
SeekBar seek = new SeekBar(context);
|
SeekBar seek = new SeekBar(context);
|
||||||
@@ -24,17 +25,16 @@ public class RoundingSeekbarDialog{
|
|||||||
|
|
||||||
mContainer.addView(seek, LayoutUtils.createLinear(-1, -2));
|
mContainer.addView(seek, LayoutUtils.createLinear(-1, -2));
|
||||||
|
|
||||||
VkAlertDialog.Builder builder = new VkAlertDialog.Builder(context);
|
new VkAlertDialog.Builder(context)
|
||||||
builder.setTitle(AndroidUtils.getString("pic_rounding_title"));
|
.setTitle(AndroidUtils.getString("pic_rounding_title"))
|
||||||
builder.setMessage(AndroidUtils.getString("pic_rounding_info"));
|
.setMessage(AndroidUtils.getString("pic_rounding_info"))
|
||||||
builder.setCancelable(true);
|
.setCancelable(true)
|
||||||
builder.setNegativeButton(AndroidUtils.getString("cancel"), null);
|
.setNegativeButton(AndroidUtils.getString("cancel"), null)
|
||||||
builder.setView(mContainer);
|
.setView(mContainer)
|
||||||
builder.setPositiveButton(AndroidUtils.getString("vtl_confirm"), (dialog, which) -> {
|
.setPositiveButton(AndroidUtils.getString("vtl_confirm"), (dialog, which) -> {
|
||||||
edit().putInt("pic_rounding", seek.getProgress()).commit();
|
edit().putInt("pic_rounding", seek.getProgress()).commit();
|
||||||
restartApplicationWithTimer();
|
restartApplicationWithTimer();
|
||||||
});
|
})
|
||||||
|
.show();
|
||||||
builder.show();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,7 +6,6 @@ import static ru.vtosters.lite.utils.NetworkUtils.isNetworkIsSlow;
|
|||||||
import static ru.vtosters.lite.utils.Preferences.getBoolValue;
|
import static ru.vtosters.lite.utils.Preferences.getBoolValue;
|
||||||
import static ru.vtosters.lite.utils.Preferences.hasVerification;
|
import static ru.vtosters.lite.utils.Preferences.hasVerification;
|
||||||
|
|
||||||
import android.app.Activity;
|
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
@@ -23,11 +22,11 @@ import okhttp3.Callback;
|
|||||||
import okhttp3.OkHttpClient;
|
import okhttp3.OkHttpClient;
|
||||||
import okhttp3.Request;
|
import okhttp3.Request;
|
||||||
import okhttp3.Response;
|
import okhttp3.Response;
|
||||||
|
import ru.vtosters.lite.utils.LifecycleUtils;
|
||||||
|
|
||||||
public class ServerDialog {
|
public class ServerDialog {
|
||||||
private static final OkHttpClient client = new OkHttpClient();
|
private static final OkHttpClient client = new OkHttpClient();
|
||||||
public static Boolean showAlert;
|
public static Boolean showAlert;
|
||||||
public static Activity activity;
|
|
||||||
private static String title;
|
private static String title;
|
||||||
private static String message;
|
private static String message;
|
||||||
private static String positiveButton;
|
private static String positiveButton;
|
||||||
@@ -93,20 +92,22 @@ public class ServerDialog {
|
|||||||
|
|
||||||
showAlert = true;
|
showAlert = true;
|
||||||
|
|
||||||
if (activity != null) {
|
var activity = LifecycleUtils.getCurrentActivity();
|
||||||
|
if (activity != null && getBoolValue(key, true) && showForNotVerified() && showAlert) {
|
||||||
activity.runOnUiThread(() -> {
|
activity.runOnUiThread(() -> {
|
||||||
VkAlertDialog.Builder builder = new VkAlertDialog.Builder(activity);
|
new VkAlertDialog.Builder(activity)
|
||||||
builder.setTitle(title);
|
.setTitle(title)
|
||||||
builder.setMessage(message);
|
.setMessage(message)
|
||||||
builder.setCancelable(cancelable);
|
.setCancelable(cancelable)
|
||||||
builder.setPositiveButton(positiveButton, (dialogInterface, i) -> edit().putBoolean(key, false).apply());
|
.setPositiveButton(positiveButton,
|
||||||
builder.setNeutralButton(neutralButton, (dialogInterface, i) -> {
|
(dialogInterface, i) -> edit().putBoolean(key, false).apply())
|
||||||
edit().putBoolean(key, false).apply();
|
.setNeutralButton(neutralButton, (dialogInterface, i) -> {
|
||||||
activity.startActivity(new Intent("android.intent.action.VIEW").setData(Uri.parse(link)));
|
edit().putBoolean(key, false).apply();
|
||||||
});
|
var intent = new Intent(Intent.ACTION_VIEW)
|
||||||
if (getBoolValue(key, true) && showForNotVerified() && showAlert) {
|
.setData(Uri.parse(link));
|
||||||
builder.show();
|
activity.startActivity(intent);
|
||||||
}
|
})
|
||||||
|
.show();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,20 +18,22 @@ public class Start {
|
|||||||
if (Build.VERSION.SDK_INT >= 23) {
|
if (Build.VERSION.SDK_INT >= 23) {
|
||||||
activity.requestPermissions(new String[]{"android.permission.WRITE_EXTERNAL_STORAGE"}, 228);
|
activity.requestPermissions(new String[]{"android.permission.WRITE_EXTERNAL_STORAGE"}, 228);
|
||||||
}
|
}
|
||||||
VkAlertDialog.Builder builder = new VkAlertDialog.Builder(activity);
|
if (getBoolValue("showAlert", true))
|
||||||
builder.setTitle(getString("warning"));
|
new VkAlertDialog.Builder(activity)
|
||||||
builder.setMessage(getWelcome());
|
.setTitle(getString("warning"))
|
||||||
builder.setCancelable(false);
|
.setMessage(getWelcome())
|
||||||
// android.content.DialogInterface.OnClickListener
|
.setCancelable(false)
|
||||||
builder.setPositiveButton(getString("startbtn2"), (dialogInterface, i) -> edit().putBoolean("showAlert", false).apply());
|
.setPositiveButton(getString("startbtn2"),
|
||||||
// android.content.DialogInterface.OnClickListener
|
(dialogInterface, i) -> edit().putBoolean("showAlert", false).apply()
|
||||||
builder.setNeutralButton(getString("startbtn1"), (dialogInterface, i) -> {
|
)
|
||||||
edit().putBoolean("showAlert", false).apply();
|
.setNeutralButton(getString("startbtn1"),
|
||||||
activity.startActivity(new Intent("android.intent.action.VIEW").setData(Uri.parse("https://t.me/vtosters")));
|
(dialogInterface, i) -> {
|
||||||
});
|
edit().putBoolean("showAlert", false).apply();
|
||||||
if (getBoolValue("showAlert", true)) {
|
activity.startActivity(new Intent("android.intent.action.VIEW").setData(Uri.parse("https://t.me/vtosters")));
|
||||||
builder.show();
|
}
|
||||||
}
|
)
|
||||||
|
.show();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static String getWelcome() {
|
private static String getWelcome() {
|
||||||
|
|||||||
@@ -0,0 +1,33 @@
|
|||||||
|
package ru.vtosters.lite.ui.dialogs;
|
||||||
|
|
||||||
|
import static ru.vtosters.lite.utils.AndroidUtils.edit;
|
||||||
|
import static ru.vtosters.lite.utils.AndroidUtils.getString;
|
||||||
|
import static ru.vtosters.lite.utils.Preferences.getBoolValue;
|
||||||
|
|
||||||
|
import android.app.Activity;
|
||||||
|
|
||||||
|
import com.vk.core.dialogs.alert.VkAlertDialog;
|
||||||
|
import com.vk.core.ui.themes.VKThemeHelper;
|
||||||
|
|
||||||
|
import ru.vtosters.lite.hooks.VKUIHook;
|
||||||
|
|
||||||
|
public class ThemeChanging {
|
||||||
|
public static void changeTheme(Activity activity, float[] f) {
|
||||||
|
if (getBoolValue("systemtheme", true)) {
|
||||||
|
new VkAlertDialog.Builder(activity)
|
||||||
|
.setTitle(getString("warning"))
|
||||||
|
.setMessage(getString("system_theme_warning"))
|
||||||
|
.setCancelable(false)
|
||||||
|
.setPositiveButton(getString("proxy_disable"), (dialogInterface, i) -> { // Отключить
|
||||||
|
edit().putBoolean("systemtheme", false).commit();
|
||||||
|
VKThemeHelper.b(activity, f);
|
||||||
|
VKUIHook.clearWebCache();
|
||||||
|
})
|
||||||
|
.setNeutralButton(getString("cancel"), null)
|
||||||
|
.show();
|
||||||
|
} else {
|
||||||
|
VKThemeHelper.b(activity, f);
|
||||||
|
VKUIHook.clearWebCache();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -2,6 +2,8 @@ package ru.vtosters.lite.ui.dialogs;
|
|||||||
|
|
||||||
import static ru.vtosters.lite.utils.AndroidUtils.sendToast;
|
import static ru.vtosters.lite.utils.AndroidUtils.sendToast;
|
||||||
|
|
||||||
|
import android.content.ClipData;
|
||||||
|
import android.content.ClipboardManager;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.os.Handler;
|
import android.os.Handler;
|
||||||
import android.os.Looper;
|
import android.os.Looper;
|
||||||
@@ -27,19 +29,17 @@ public class Translate {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static void showDialog(Context context, String text) {
|
private static void showDialog(Context context, String text) {
|
||||||
VkAlertDialog.Builder alertDialog = new VkAlertDialog.Builder(context);
|
new VkAlertDialog.Builder(context)
|
||||||
alertDialog.setTitle(AndroidUtils.getString("translator_title"));
|
.setTitle(AndroidUtils.getString("translator_title"))
|
||||||
alertDialog.setMessage(text);
|
.setMessage(text)
|
||||||
alertDialog.setPositiveButton(AndroidUtils.getString("close"), (dialog, which) -> {
|
.setPositiveButton(AndroidUtils.getString("close"),
|
||||||
dialog.cancel();
|
(dialog, which) -> dialog.cancel())
|
||||||
});
|
.setNeutralButton(AndroidUtils.getString("copy"), (dialog, which) -> {
|
||||||
alertDialog.setNeutralButton(AndroidUtils.getString("copy"), (dialog, which) -> {
|
var clipboard = (ClipboardManager) context.getSystemService(Context.CLIPBOARD_SERVICE);
|
||||||
android.content.ClipboardManager clipboard = (android.content.ClipboardManager) context.getSystemService(Context.CLIPBOARD_SERVICE);
|
var clip = ClipData.newPlainText("Copied Text", text);
|
||||||
android.content.ClipData clip = android.content.ClipData.newPlainText("Copied Text", text);
|
clipboard.setPrimaryClip(clip);
|
||||||
clipboard.setPrimaryClip(clip);
|
sendToast(AndroidUtils.getString("copied_to_clipboard"));
|
||||||
sendToast(AndroidUtils.getString("copied_to_clipboard"));
|
})
|
||||||
});
|
.show();
|
||||||
var alert = alertDialog.create();
|
|
||||||
alert.show();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,22 +16,23 @@ import ru.vtosters.lite.ui.fragments.VKUIwrapper;
|
|||||||
|
|
||||||
public class VKIDProtection {
|
public class VKIDProtection {
|
||||||
public static void alert(final Activity activity) {
|
public static void alert(final Activity activity) {
|
||||||
VkAlertDialog.Builder builder = new VkAlertDialog.Builder(activity);
|
if (!getBoolValue("showAlertVkId", true)) return;
|
||||||
builder.setTitle(getString("warning"));
|
new VkAlertDialog.Builder(activity)
|
||||||
builder.setMessage(getString("vkidsumm"));
|
.setTitle(getString("warning"))
|
||||||
builder.setCancelable(false);
|
.setMessage(getString("vkidsumm"))
|
||||||
// android.content.DialogInterface.OnClickListener
|
.setCancelable(false)
|
||||||
builder.setPositiveButton(getString("startbtn2"), (dialogInterface, i) -> edit().putBoolean("showAlertVkId", false).apply());
|
.setPositiveButton(getString("startbtn2"),
|
||||||
// android.content.DialogInterface.OnClickListener
|
(dialogInterface, i) -> edit().putBoolean("showAlertVkId", false).apply())
|
||||||
builder.setNeutralButton(getString("vkiddisable"), (dialogInterface, i) -> {
|
.setNeutralButton(getString("vkiddisable"), (dialogInterface, i) -> {
|
||||||
edit().putBoolean("showAlertVkId", false).apply();
|
edit().putBoolean("showAlertVkId", false).apply();
|
||||||
VKUIwrapper.setLink((isAnyProxyEnabled() ? "https://id.vk.com/account" : "https://" + getApi() + "/_/id.vk.com/account"));
|
VKUIwrapper.setLink(
|
||||||
Intent a2 = new Navigator(VKUIwrapper.class).b(activity);
|
isAnyProxyEnabled()
|
||||||
a2.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
? "https://id.vk.com/account"
|
||||||
activity.startActivity(a2);
|
: "https://" + getApi() + "/_/id.vk.com/account");
|
||||||
});
|
var intent = new Navigator(VKUIwrapper.class).b(activity)
|
||||||
if (getBoolValue("showAlertVkId", true)) {
|
.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||||
builder.show();
|
activity.startActivity(intent);
|
||||||
}
|
})
|
||||||
|
.show();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,15 +23,15 @@ import com.vtosters.lite.general.fragments.MaterialPreferenceToolbarFragment;
|
|||||||
import ru.vtosters.lite.ui.components.NewsfeedListManager;
|
import ru.vtosters.lite.ui.components.NewsfeedListManager;
|
||||||
import ru.vtosters.lite.utils.AndroidUtils;
|
import ru.vtosters.lite.utils.AndroidUtils;
|
||||||
|
|
||||||
public class FeedFragment extends MaterialPreferenceToolbarFragment{
|
public class FeedFragment extends MaterialPreferenceToolbarFragment {
|
||||||
@Override
|
@Override
|
||||||
public void onCreate(Bundle bundle){
|
public void onCreate(Bundle bundle) {
|
||||||
super.onCreate(bundle);
|
super.onCreate(bundle);
|
||||||
addPreferencesFromResource(getIdentifier("preferences_feed", "xml"));
|
addPreferencesFromResource(getIdentifier("preferences_feed", "xml"));
|
||||||
prefs();
|
prefs();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void prefs(){
|
private void prefs() {
|
||||||
findPreference("officialnewssett").setOnPreferenceClickListener(new openofficialsett());
|
findPreference("officialnewssett").setOnPreferenceClickListener(new openofficialsett());
|
||||||
findPreference("cringecopyright").setEnabled(!copyright_post());
|
findPreference("cringecopyright").setEnabled(!copyright_post());
|
||||||
|
|
||||||
@@ -43,7 +43,7 @@ public class FeedFragment extends MaterialPreferenceToolbarFragment{
|
|||||||
setupFilters();
|
setupFilters();
|
||||||
return true;
|
return true;
|
||||||
});
|
});
|
||||||
|
|
||||||
findPreference("sourcenamefilter").setOnPreferenceClickListener(preference -> {
|
findPreference("sourcenamefilter").setOnPreferenceClickListener(preference -> {
|
||||||
setupFilters();
|
setupFilters();
|
||||||
return true;
|
return true;
|
||||||
@@ -81,7 +81,7 @@ public class FeedFragment extends MaterialPreferenceToolbarFragment{
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private String count(String text){
|
private String count(String text) {
|
||||||
// count comma separated words in string
|
// count comma separated words in string
|
||||||
var count = text.split(", ").length;
|
var count = text.split(", ").length;
|
||||||
|
|
||||||
@@ -92,21 +92,22 @@ public class FeedFragment extends MaterialPreferenceToolbarFragment{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void remdialog(String key, Context context){
|
private void remdialog(String key, Context context) {
|
||||||
VkAlertDialog.Builder builder = new VkAlertDialog.Builder(context);
|
new VkAlertDialog.Builder(context)
|
||||||
builder.setTitle(AndroidUtils.getString("warning"));
|
.setTitle(AndroidUtils.getString("warning"))
|
||||||
builder.setMessage(AndroidUtils.getString("delete_elements_confirm"));
|
.setMessage(AndroidUtils.getString("delete_elements_confirm"))
|
||||||
builder.setCancelable(false);
|
.setCancelable(false)
|
||||||
builder.setPositiveButton(AndroidUtils.getString("yes"), (dialogInterface, i) -> {
|
.setPositiveButton(AndroidUtils.getString("yes"), (dialogInterface, i) -> {
|
||||||
edit().remove(key).apply();
|
edit().remove(key).apply();
|
||||||
sendToast(AndroidUtils.getString("elements_deleted_success"));
|
sendToast(AndroidUtils.getString("elements_deleted_success"));
|
||||||
setupFilters();
|
setupFilters();
|
||||||
});
|
})
|
||||||
builder.setNegativeButton(AndroidUtils.getString("cancel"), (dialogInterface, i) -> dialogInterface.dismiss());
|
.setNegativeButton(AndroidUtils.getString("cancel"),
|
||||||
builder.show();
|
(dialogInterface, i) -> dialogInterface.dismiss())
|
||||||
|
.show();
|
||||||
}
|
}
|
||||||
|
|
||||||
private String countSet(String key){
|
private String countSet(String key) {
|
||||||
var set = getDefaultPrefs().getStringSet(key, null);
|
var set = getDefaultPrefs().getStringSet(key, null);
|
||||||
StringBuilder str = new StringBuilder();
|
StringBuilder str = new StringBuilder();
|
||||||
if (set != null) {
|
if (set != null) {
|
||||||
@@ -126,15 +127,15 @@ public class FeedFragment extends MaterialPreferenceToolbarFragment{
|
|||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean onPreferenceTreeClick(Preference preference){
|
public boolean onPreferenceTreeClick(Preference preference) {
|
||||||
findPreference("cringecopyright").setEnabled(!copyright_post());
|
findPreference("cringecopyright").setEnabled(!copyright_post());
|
||||||
setupFilters();
|
setupFilters();
|
||||||
return super.onPreferenceTreeClick(preference);
|
return super.onPreferenceTreeClick(preference);
|
||||||
}
|
}
|
||||||
|
|
||||||
public class openofficialsett implements Preference.OnPreferenceClickListener{
|
public class openofficialsett implements Preference.OnPreferenceClickListener {
|
||||||
@Override // android.support.v7.preference.Preference.c
|
@Override // android.support.v7.preference.Preference.c
|
||||||
public boolean onPreferenceClick(Preference preference){
|
public boolean onPreferenceClick(Preference preference) {
|
||||||
Context context = requireContext();
|
Context context = requireContext();
|
||||||
Intent a2 = new Navigator(NewsfeedSettingsFragment.class).b(context);
|
Intent a2 = new Navigator(NewsfeedSettingsFragment.class).b(context);
|
||||||
a2.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
a2.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||||
|
|||||||
@@ -15,13 +15,10 @@ import static ru.vtosters.lite.utils.AndroidUtils.sendToast;
|
|||||||
import static ru.vtosters.lite.utils.Preferences.getBoolValue;
|
import static ru.vtosters.lite.utils.Preferences.getBoolValue;
|
||||||
import static ru.vtosters.lite.utils.Preferences.hasVerification;
|
import static ru.vtosters.lite.utils.Preferences.hasVerification;
|
||||||
import static ru.vtosters.lite.utils.Preferences.preferences;
|
import static ru.vtosters.lite.utils.Preferences.preferences;
|
||||||
import static ru.vtosters.lite.utils.ThemesUtils.getAccentColor;
|
|
||||||
import static ru.vtosters.lite.utils.ThemesUtils.getAlertStyle;
|
|
||||||
import static ru.vtosters.lite.utils.ThemesUtils.getTextAttr;
|
import static ru.vtosters.lite.utils.ThemesUtils.getTextAttr;
|
||||||
|
|
||||||
import android.annotation.SuppressLint;
|
import android.annotation.SuppressLint;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.DialogInterface;
|
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.graphics.drawable.Drawable;
|
import android.graphics.drawable.Drawable;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
@@ -30,10 +27,10 @@ import android.util.TypedValue;
|
|||||||
import android.widget.RadioButton;
|
import android.widget.RadioButton;
|
||||||
import android.widget.RadioGroup;
|
import android.widget.RadioGroup;
|
||||||
|
|
||||||
import androidx.appcompat.app.AlertDialog;
|
|
||||||
import androidx.appcompat.view.ContextThemeWrapper;
|
import androidx.appcompat.view.ContextThemeWrapper;
|
||||||
import androidx.core.content.res.ResourcesCompat;
|
import androidx.core.content.res.ResourcesCompat;
|
||||||
|
|
||||||
|
import com.vk.core.dialogs.alert.VkAlertDialog;
|
||||||
import com.vtosters.lite.general.fragments.MaterialPreferenceToolbarFragment;
|
import com.vtosters.lite.general.fragments.MaterialPreferenceToolbarFragment;
|
||||||
|
|
||||||
import ru.vtosters.lite.utils.AndroidUtils;
|
import ru.vtosters.lite.utils.AndroidUtils;
|
||||||
@@ -73,37 +70,30 @@ public class IconsFragment extends MaterialPreferenceToolbarFragment {
|
|||||||
rgVK.setChecked(defname.contains("standard"));
|
rgVK.setChecked(defname.contains("standard"));
|
||||||
rgDefault.setChecked(defname.contains("vt") || defname.isEmpty());
|
rgDefault.setChecked(defname.contains("vt") || defname.isEmpty());
|
||||||
|
|
||||||
AlertDialog.Builder builder = new AlertDialog.Builder(ctx, getAlertStyle());
|
new VkAlertDialog.Builder(ctx)
|
||||||
builder.setTitle(AndroidUtils.getString("app_name_select_title"));
|
.setTitle(AndroidUtils.getString("app_name_select_title"))
|
||||||
builder.setView(rg);
|
.setView(rg)
|
||||||
builder.setPositiveButton(AndroidUtils.getString("vtl_confirm"), ((dialog, which) -> {
|
.setPositiveButton(AndroidUtils.getString("vtl_confirm"), ((dialog, which) -> {
|
||||||
if (rgDefault.isChecked()) {
|
if (rgDefault.isChecked()) {
|
||||||
edit().putString("appname", "vt").commit();
|
edit().putString("appname", "vt").commit();
|
||||||
edit().putString("selectedicon", appicon).commit();
|
edit().putString("selectedicon", appicon).commit();
|
||||||
|
|
||||||
switchComponent(appicon, "vt", deficon, defname);
|
switchComponent(appicon, "vt", deficon, defname);
|
||||||
} else if (rgVK.isChecked()) {
|
} else if (rgVK.isChecked()) {
|
||||||
edit().putString("appname", "standard").commit();
|
edit().putString("appname", "standard").commit();
|
||||||
edit().putString("selectedicon", appicon).commit();
|
edit().putString("selectedicon", appicon).commit();
|
||||||
|
|
||||||
switchComponent(appicon, "standard", deficon, defname);
|
switchComponent(appicon, "standard", deficon, defname);
|
||||||
} else if (rgVKontakte.isChecked()) {
|
} else if (rgVKontakte.isChecked()) {
|
||||||
edit().putString("appname", "vkontakte").commit();
|
edit().putString("appname", "vkontakte").commit();
|
||||||
edit().putString("selectedicon", appicon).commit();
|
edit().putString("selectedicon", appicon).commit();
|
||||||
|
|
||||||
switchComponent(appicon, "vkontakte", deficon, defname);
|
switchComponent(appicon, "vkontakte", deficon, defname);
|
||||||
}
|
}
|
||||||
}));
|
}))
|
||||||
builder.setNegativeButton(AndroidUtils.getString("cancel"), ((dialog, which) -> {
|
.setNegativeButton(AndroidUtils.getString("cancel"),
|
||||||
dialog.dismiss();
|
((dialog, which) -> dialog.dismiss()))
|
||||||
}));
|
.show();
|
||||||
|
|
||||||
var alert = builder.create();
|
|
||||||
|
|
||||||
alert.show();
|
|
||||||
|
|
||||||
alert.getButton(DialogInterface.BUTTON_POSITIVE).setTextColor(getAccentColor());
|
|
||||||
alert.getButton(DialogInterface.BUTTON_NEGATIVE).setTextColor(getAccentColor());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressLint("UseCompatLoadingForDrawables")
|
@SuppressLint("UseCompatLoadingForDrawables")
|
||||||
|
|||||||
@@ -7,7 +7,6 @@ import static ru.vtosters.lite.utils.LifecycleUtils.restartApplicationWithTimer;
|
|||||||
|
|
||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.view.View;
|
|
||||||
|
|
||||||
import androidx.preference.Preference;
|
import androidx.preference.Preference;
|
||||||
|
|
||||||
@@ -29,7 +28,7 @@ public class InterfaceFragment extends MaterialPreferenceToolbarFragment {
|
|||||||
findPreference("swipe").setOnPreferenceClickListener(new restart());
|
findPreference("swipe").setOnPreferenceClickListener(new restart());
|
||||||
findPreference("is_likes_on_right").setOnPreferenceClickListener(new restart());
|
findPreference("is_likes_on_right").setOnPreferenceClickListener(new restart());
|
||||||
|
|
||||||
if (isTablet()){
|
if (isTablet()) {
|
||||||
findPreference("menusett").setVisible(false);
|
findPreference("menusett").setVisible(false);
|
||||||
findPreference("swipe").setVisible(false);
|
findPreference("swipe").setVisible(false);
|
||||||
}
|
}
|
||||||
@@ -39,7 +38,7 @@ public class InterfaceFragment extends MaterialPreferenceToolbarFragment {
|
|||||||
return true;
|
return true;
|
||||||
});
|
});
|
||||||
|
|
||||||
if (Build.VERSION.SDK_INT >= 33){
|
if (Build.VERSION.SDK_INT >= 33) {
|
||||||
findPreference("anim_rtrn_type").setVisible(false);
|
findPreference("anim_rtrn_type").setVisible(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -10,25 +10,21 @@ import static ru.vtosters.lite.utils.AndroidUtils.getIdentifier;
|
|||||||
import static ru.vtosters.lite.utils.AndroidUtils.getPreferences;
|
import static ru.vtosters.lite.utils.AndroidUtils.getPreferences;
|
||||||
import static ru.vtosters.lite.utils.AndroidUtils.sendToast;
|
import static ru.vtosters.lite.utils.AndroidUtils.sendToast;
|
||||||
import static ru.vtosters.lite.utils.LifecycleUtils.restartApplicationWithTimer;
|
import static ru.vtosters.lite.utils.LifecycleUtils.restartApplicationWithTimer;
|
||||||
import static ru.vtosters.lite.utils.NewsFeedFiltersUtils.setupFilters;
|
|
||||||
import static ru.vtosters.lite.utils.ThemesUtils.getAccentColor;
|
import static ru.vtosters.lite.utils.ThemesUtils.getAccentColor;
|
||||||
import static ru.vtosters.lite.utils.ThemesUtils.getAlertStyle;
|
|
||||||
import static ru.vtosters.lite.utils.ThemesUtils.getSTextAttr;
|
import static ru.vtosters.lite.utils.ThemesUtils.getSTextAttr;
|
||||||
import static ru.vtosters.lite.utils.ThemesUtils.getTextAttr;
|
import static ru.vtosters.lite.utils.ThemesUtils.getTextAttr;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.DialogInterface;
|
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.content.res.ColorStateList;
|
import android.content.res.ColorStateList;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.view.LayoutInflater;
|
import android.view.Gravity;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
import android.widget.EditText;
|
import android.widget.EditText;
|
||||||
|
import android.widget.FrameLayout;
|
||||||
import android.widget.LinearLayout;
|
import android.widget.LinearLayout;
|
||||||
import android.widget.ListView;
|
|
||||||
|
|
||||||
import androidx.appcompat.app.AlertDialog;
|
|
||||||
import androidx.preference.Preference;
|
import androidx.preference.Preference;
|
||||||
|
|
||||||
import com.vk.core.dialogs.alert.VkAlertDialog;
|
import com.vk.core.dialogs.alert.VkAlertDialog;
|
||||||
@@ -39,22 +35,42 @@ import org.json.JSONObject;
|
|||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
import java.util.concurrent.ExecutorService;
|
||||||
|
import java.util.concurrent.Executors;
|
||||||
|
|
||||||
import okhttp3.Headers;
|
import okhttp3.Headers;
|
||||||
import okhttp3.OkHttpClient;
|
import okhttp3.OkHttpClient;
|
||||||
import okhttp3.Request;
|
import okhttp3.Request;
|
||||||
|
import ru.vtosters.lite.downloaders.AudioDownloader;
|
||||||
import ru.vtosters.lite.downloaders.VideoDownloader;
|
import ru.vtosters.lite.downloaders.VideoDownloader;
|
||||||
import ru.vtosters.lite.music.Scrobbler;
|
import ru.vtosters.lite.music.Scrobbler;
|
||||||
|
import ru.vtosters.lite.music.cache.CacheDatabaseDelegate;
|
||||||
import ru.vtosters.lite.ui.adapters.ImagineArrayAdapter;
|
import ru.vtosters.lite.ui.adapters.ImagineArrayAdapter;
|
||||||
import ru.vtosters.lite.utils.AndroidUtils;
|
import ru.vtosters.lite.utils.AndroidUtils;
|
||||||
import ru.vtosters.lite.utils.LifecycleUtils;
|
|
||||||
|
|
||||||
public class MediaFragment extends MaterialPreferenceToolbarFragment {
|
public class MediaFragment extends MaterialPreferenceToolbarFragment {
|
||||||
private final int REQUEST_CODE_SET_DOWNLOAD_DIRECTORY = 665;
|
private static final ExecutorService executor = Executors.newCachedThreadPool();
|
||||||
private final int REQUEST_CODE_SET_MUSIC_DIRECTORY = 666;
|
|
||||||
private final int REQUEST_CODE_SET_PHOTOS_DIRECTORY = 667;
|
|
||||||
private final int REQUEST_CODE_SET_VIDEOS_DIRECTORY = 668;
|
|
||||||
|
|
||||||
|
public static void download(Context ctx) {
|
||||||
|
final EditText input = new EditText(ctx);
|
||||||
|
input.setTextColor(getTextAttr());
|
||||||
|
input.setBackgroundTintList(ColorStateList.valueOf(getAccentColor()));
|
||||||
|
|
||||||
|
var lp = new FrameLayout.LayoutParams(-1, -2);
|
||||||
|
lp.leftMargin = AndroidUtils.dp2px(16);
|
||||||
|
lp.rightMargin = AndroidUtils.dp2px(16);
|
||||||
|
lp.gravity = Gravity.CENTER;
|
||||||
|
var container = new FrameLayout(ctx);
|
||||||
|
|
||||||
|
container.addView(input, lp);
|
||||||
|
|
||||||
|
new VkAlertDialog.Builder(ctx)
|
||||||
|
.setTitle(AndroidUtils.getString("video_dl_enter_link"))
|
||||||
|
.setPositiveButton(AndroidUtils.getString("download"),
|
||||||
|
(dialog, which) -> VideoDownloader.parseVideoLink(input.getText().toString(), ctx))
|
||||||
|
.setView(container)
|
||||||
|
.show();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onCreate(Bundle bundle) {
|
public void onCreate(Bundle bundle) {
|
||||||
@@ -95,7 +111,22 @@ public class MediaFragment extends MaterialPreferenceToolbarFragment {
|
|||||||
findPreference("lastfm_enabled").setEnabled(false);
|
findPreference("lastfm_enabled").setEnabled(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!isVkxInstalled()){
|
findPreference("cached_tracks").setSummary(String.format(AndroidUtils.getString("cached_tracks_counter"), CacheDatabaseDelegate.getTrackCount()));
|
||||||
|
findPreference("cached_tracks").setOnPreferenceClickListener(preference -> {
|
||||||
|
if (CacheDatabaseDelegate.getTrackCount() == 0) {
|
||||||
|
sendToast(AndroidUtils.getString("no_cache_error"));
|
||||||
|
} else {
|
||||||
|
delcache(requireContext());
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
|
||||||
|
findPreference("audio_download").setOnPreferenceClickListener(preference -> {
|
||||||
|
dlaudio(requireContext());
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!isVkxInstalled()) {
|
||||||
findPreference("vkx_sett").setVisible(false);
|
findPreference("vkx_sett").setVisible(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -106,19 +137,15 @@ public class MediaFragment extends MaterialPreferenceToolbarFragment {
|
|||||||
new ImagineArrayAdapter.ImagineArrayAdapterItem(getIdentifier("microsoft", "drawable"), "Bing")
|
new ImagineArrayAdapter.ImagineArrayAdapterItem(getIdentifier("microsoft", "drawable"), "Bing")
|
||||||
);
|
);
|
||||||
|
|
||||||
var alert = new VkAlertDialog.Builder(getActivity())
|
var adapter = new ImagineArrayAdapter(getContext(), items);
|
||||||
.create();
|
|
||||||
|
|
||||||
var listView = (ListView) LayoutInflater.from(getContext()).inflate(com.vtosters.lite.R.layout.abc_select_dialog_material, null, false);
|
|
||||||
var adapter = new ImagineArrayAdapter(getContext(), items, i -> {
|
|
||||||
getPreferences().edit().putInt("search_engine", i).apply();
|
|
||||||
alert.dismiss();
|
|
||||||
});
|
|
||||||
adapter.setSelected(getPreferences().getInt("search_engine", 0));
|
adapter.setSelected(getPreferences().getInt("search_engine", 0));
|
||||||
listView.setAdapter(adapter);
|
|
||||||
alert.setView(listView);
|
|
||||||
alert.show();
|
|
||||||
|
|
||||||
|
new VkAlertDialog.Builder(getActivity())
|
||||||
|
.setAdapter(adapter, (dialog, which) -> {
|
||||||
|
getPreferences().edit().putInt("search_engine", which).apply();
|
||||||
|
dialog.cancel();
|
||||||
|
})
|
||||||
|
.show();
|
||||||
return true;
|
return true;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -147,38 +174,55 @@ public class MediaFragment extends MaterialPreferenceToolbarFragment {
|
|||||||
ln.getLayoutParams().width = ViewGroup.LayoutParams.MATCH_PARENT;
|
ln.getLayoutParams().width = ViewGroup.LayoutParams.MATCH_PARENT;
|
||||||
ln.setLayoutParams(margin);
|
ln.setLayoutParams(margin);
|
||||||
|
|
||||||
AlertDialog.Builder alertDialog = new AlertDialog.Builder(ctx, getAlertStyle());
|
new VkAlertDialog.Builder(ctx)
|
||||||
alertDialog.setTitle(AndroidUtils.getString("lastfm_enter_credentials"));
|
.setTitle(AndroidUtils.getString("lastfm_enter_credentials"))
|
||||||
|
.setPositiveButton(AndroidUtils.getString("lastfm_enter"),
|
||||||
alertDialog.setView(linearLayout);
|
(dialog, which) -> {
|
||||||
alertDialog.setPositiveButton(AndroidUtils.getString("lastfm_enter"), (dialog, which) -> {
|
String login = fn.getText().toString();
|
||||||
String login = fn.getText().toString();
|
String pass = ln.getText().toString();
|
||||||
String pass = ln.getText().toString();
|
Scrobbler.auth(login, pass);
|
||||||
|
}
|
||||||
Scrobbler.auth(login, pass);
|
)
|
||||||
});
|
.setView(linearLayout)
|
||||||
var alert = alertDialog.create();
|
.show();
|
||||||
alert.show();
|
|
||||||
alert.getButton(DialogInterface.BUTTON_POSITIVE).setTextColor(getAccentColor());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void logout(Context ctx) {
|
private void logout(Context ctx) {
|
||||||
VkAlertDialog.Builder alertDialog = new VkAlertDialog.Builder(ctx);
|
new VkAlertDialog.Builder(ctx)
|
||||||
alertDialog.setTitle(AndroidUtils.getString("lastfm_logout_title"));
|
.setTitle(AndroidUtils.getString("lastfm_logout_title"))
|
||||||
alertDialog.setMessage(AndroidUtils.getString("lastfm_logout_confirm"));
|
.setMessage(AndroidUtils.getString("lastfm_logout_confirm"))
|
||||||
alertDialog.setPositiveButton(AndroidUtils.getString("vkim_yes"), (dialog, which) -> {
|
.setPositiveButton(AndroidUtils.getString("vkim_yes"),
|
||||||
Scrobbler.logout();
|
(dialog, which) -> Scrobbler.logout())
|
||||||
});
|
.setNeutralButton(AndroidUtils.getString("vkim_no"),
|
||||||
alertDialog.setNeutralButton(AndroidUtils.getString("vkim_no"), (dialog, which) -> {
|
(dialog, which) -> dialog.cancel())
|
||||||
dialog.cancel();
|
.show();
|
||||||
});
|
|
||||||
var alert = alertDialog.create();
|
|
||||||
alert.show();
|
|
||||||
alert.getButton(DialogInterface.BUTTON_POSITIVE).setTextColor(getAccentColor());
|
|
||||||
alert.getButton(DialogInterface.BUTTON_NEUTRAL).setTextColor(getResources().getColor(com.vtosters.lite.R.color.red));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void deleteVideoHistory() {
|
private void delcache(Context ctx) {
|
||||||
|
new VkAlertDialog.Builder(ctx)
|
||||||
|
.setTitle(AndroidUtils.getString("warning"))
|
||||||
|
.setMessage(AndroidUtils.getString("cached_tracks_remove_confirm"))
|
||||||
|
.setPositiveButton(AndroidUtils.getString("yes"),
|
||||||
|
(dialog, which) -> executor.submit(CacheDatabaseDelegate::clear))
|
||||||
|
.setNeutralButton(AndroidUtils.getString("no"),
|
||||||
|
(dialog, which) -> dialog.cancel())
|
||||||
|
.show();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void dlaudio(Context ctx) {
|
||||||
|
new VkAlertDialog.Builder(ctx)
|
||||||
|
.setTitle(AndroidUtils.getString("download_method"))
|
||||||
|
.setMessage(AndroidUtils.getString("download_method_desc"))
|
||||||
|
.setPositiveButton(AndroidUtils.getString("download_method_cache"), (dialog, which) -> {
|
||||||
|
executor.submit(AudioDownloader::cacheAllAudios);
|
||||||
|
})
|
||||||
|
.setNegativeButton(AndroidUtils.getString("download_method_mp3"), (dialog, which) -> {
|
||||||
|
executor.submit(AudioDownloader::downloadAllAudios);
|
||||||
|
})
|
||||||
|
.show();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void deleteVideoHistory() {
|
||||||
Thread thread = new Thread(() -> {
|
Thread thread = new Thread(() -> {
|
||||||
try {
|
try {
|
||||||
var request = new Request.a()
|
var request = new Request.a()
|
||||||
@@ -189,10 +233,10 @@ public class MediaFragment extends MaterialPreferenceToolbarFragment {
|
|||||||
try {
|
try {
|
||||||
var response = new JSONObject(new OkHttpClient().a(request).execute().a().g());
|
var response = new JSONObject(new OkHttpClient().a(request).execute().a().g());
|
||||||
|
|
||||||
if (response.optInt("response") == 1){
|
if (response.optInt("response") == 1) {
|
||||||
LifecycleUtils.getCurrentActivity().runOnUiThread(() -> sendToast(AndroidUtils.getString("video_history_cleaned")));
|
requireActivity().runOnUiThread(() -> sendToast(AndroidUtils.getString("video_history_cleaned")));
|
||||||
} else {
|
} else {
|
||||||
LifecycleUtils.getCurrentActivity().runOnUiThread(() -> sendToast("Ошибка при очистке истории. Подробности в логах"));
|
requireActivity().runOnUiThread(() -> sendToast(AndroidUtils.getString("delete_video_history_error")));
|
||||||
}
|
}
|
||||||
|
|
||||||
Log.d("VideoHistory", response.toString());
|
Log.d("VideoHistory", response.toString());
|
||||||
@@ -207,42 +251,16 @@ public class MediaFragment extends MaterialPreferenceToolbarFragment {
|
|||||||
thread.start();
|
thread.start();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void deleteVideoHistoryDialog(Context context){
|
private void deleteVideoHistoryDialog(Context context) {
|
||||||
VkAlertDialog.Builder builder = new VkAlertDialog.Builder(context);
|
new VkAlertDialog.Builder(context)
|
||||||
builder.setTitle(AndroidUtils.getString("warning"));
|
.setTitle(AndroidUtils.getString("warning"))
|
||||||
builder.setMessage("Вы действительно хотите очистить историю видео?");
|
.setMessage(AndroidUtils.getString("delete_video_history_confirm"))
|
||||||
builder.setCancelable(false);
|
.setCancelable(false)
|
||||||
builder.setPositiveButton(AndroidUtils.getString("yes"), (dialogInterface, i) -> {
|
.setPositiveButton(AndroidUtils.getString("yes"),
|
||||||
deleteVideoHistory();
|
(dialogInterface, i) -> deleteVideoHistory())
|
||||||
});
|
.setNegativeButton(AndroidUtils.getString("cancel"),
|
||||||
builder.setNegativeButton(AndroidUtils.getString("cancel"), (dialogInterface, i) -> dialogInterface.dismiss());
|
(dialogInterface, i) -> dialogInterface.dismiss())
|
||||||
builder.show();
|
.show();
|
||||||
}
|
|
||||||
|
|
||||||
public static void download(Context ctx) {
|
|
||||||
AlertDialog.Builder alertDialog = new AlertDialog.Builder(ctx, getAlertStyle());
|
|
||||||
alertDialog.setTitle(AndroidUtils.getString("video_dl_enter_link"));
|
|
||||||
|
|
||||||
final EditText input = new EditText(ctx);
|
|
||||||
LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(
|
|
||||||
LinearLayout.LayoutParams.MATCH_PARENT,
|
|
||||||
LinearLayout.LayoutParams.MATCH_PARENT);
|
|
||||||
input.setLayoutParams(lp);
|
|
||||||
input.setTextColor(getTextAttr());
|
|
||||||
input.setBackgroundTintList(ColorStateList.valueOf(getAccentColor()));
|
|
||||||
alertDialog.setView(input);
|
|
||||||
alertDialog.setPositiveButton(AndroidUtils.getString("download"), (dialog, which) -> VideoDownloader.parseVideoLink(input.getText().toString(), ctx));
|
|
||||||
var alert = alertDialog.create();
|
|
||||||
alert.show();
|
|
||||||
alert.getButton(DialogInterface.BUTTON_POSITIVE).setTextColor(getAccentColor());
|
|
||||||
}
|
|
||||||
|
|
||||||
private class download implements Preference.OnPreferenceClickListener {
|
|
||||||
@Override // android.support.v7.preference.Preference.c
|
|
||||||
public boolean onPreferenceClick(Preference preference) {
|
|
||||||
download(getActivity());
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class restart implements Preference.OnPreferenceChangeListener {
|
private static class restart implements Preference.OnPreferenceChangeListener {
|
||||||
@@ -253,4 +271,12 @@ public class MediaFragment extends MaterialPreferenceToolbarFragment {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private class download implements Preference.OnPreferenceClickListener {
|
||||||
|
@Override // android.support.v7.preference.Preference.c
|
||||||
|
public boolean onPreferenceClick(Preference preference) {
|
||||||
|
download(getActivity());
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,8 +13,6 @@ import android.annotation.SuppressLint;
|
|||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.view.LayoutInflater;
|
|
||||||
import android.widget.ListView;
|
|
||||||
|
|
||||||
import androidx.preference.Preference;
|
import androidx.preference.Preference;
|
||||||
|
|
||||||
@@ -51,18 +49,15 @@ public class MessagesFragment extends MaterialPreferenceToolbarFragment {
|
|||||||
// new ImagineArrayAdapter.ImagineArrayAdapterItem(getIdentifier("ic_deepl_logo_icon", "drawable"), "DeepL")
|
// new ImagineArrayAdapter.ImagineArrayAdapterItem(getIdentifier("ic_deepl_logo_icon", "drawable"), "DeepL")
|
||||||
);
|
);
|
||||||
|
|
||||||
var alert = new VkAlertDialog.Builder(getActivity())
|
var adapter = new ImagineArrayAdapter(requireContext(), items);
|
||||||
.create();
|
|
||||||
|
|
||||||
var listView = (ListView) LayoutInflater.from(getContext()).inflate(com.vtosters.lite.R.layout.abc_select_dialog_material, null, false);
|
|
||||||
var adapter = new ImagineArrayAdapter(requireContext(), items, i -> {
|
|
||||||
getPreferences().edit().putInt("translator", i).apply();
|
|
||||||
alert.dismiss();
|
|
||||||
});
|
|
||||||
adapter.setSelected(getPreferences().getInt("translator", 0));
|
adapter.setSelected(getPreferences().getInt("translator", 0));
|
||||||
listView.setAdapter(adapter);
|
|
||||||
alert.setView(listView);
|
new VkAlertDialog.Builder(getActivity())
|
||||||
alert.show();
|
.setAdapter(adapter, (dialog, which) -> {
|
||||||
|
getPreferences().edit().putInt("translator", which).apply();
|
||||||
|
dialog.cancel();
|
||||||
|
})
|
||||||
|
.show();
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
});
|
});
|
||||||
@@ -71,7 +66,7 @@ public class MessagesFragment extends MaterialPreferenceToolbarFragment {
|
|||||||
findPreference("wallpapers").setIcon(recolorDrawable(getGlobalContext().getDrawable(getIdentifier("ic_media_outline_28", "drawable"))));
|
findPreference("wallpapers").setIcon(recolorDrawable(getGlobalContext().getDrawable(getIdentifier("ic_media_outline_28", "drawable"))));
|
||||||
findPreference("vkme").setIcon(getIdentifier("ic_vkme_28", "drawable"));
|
findPreference("vkme").setIcon(getIdentifier("ic_vkme_28", "drawable"));
|
||||||
|
|
||||||
if (isTablet()){
|
if (isTablet()) {
|
||||||
findPreference("alteremoji").setVisible(false);
|
findPreference("alteremoji").setVisible(false);
|
||||||
findPreference("vkmesett").setVisible(false);
|
findPreference("vkmesett").setVisible(false);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,7 +11,6 @@ import static ru.vtosters.lite.utils.AccountManagerUtils.getUserToken;
|
|||||||
import static ru.vtosters.lite.utils.AndroidUtils.dp2px;
|
import static ru.vtosters.lite.utils.AndroidUtils.dp2px;
|
||||||
import static ru.vtosters.lite.utils.AndroidUtils.getDefaultPrefs;
|
import static ru.vtosters.lite.utils.AndroidUtils.getDefaultPrefs;
|
||||||
import static ru.vtosters.lite.utils.AndroidUtils.getIdentifier;
|
import static ru.vtosters.lite.utils.AndroidUtils.getIdentifier;
|
||||||
import static ru.vtosters.lite.utils.ContactsUtils.setContactsSync;
|
|
||||||
import static ru.vtosters.lite.utils.LifecycleUtils.restartApplication;
|
import static ru.vtosters.lite.utils.LifecycleUtils.restartApplication;
|
||||||
import static ru.vtosters.lite.utils.ThemesUtils.getTextAttr;
|
import static ru.vtosters.lite.utils.ThemesUtils.getTextAttr;
|
||||||
|
|
||||||
@@ -57,6 +56,7 @@ import ru.vtosters.lite.ui.activities.VKAdminTokenActivity;
|
|||||||
import ru.vtosters.lite.ui.components.BackupManager;
|
import ru.vtosters.lite.ui.components.BackupManager;
|
||||||
import ru.vtosters.lite.utils.AndroidUtils;
|
import ru.vtosters.lite.utils.AndroidUtils;
|
||||||
import ru.vtosters.lite.utils.ContactsUtils;
|
import ru.vtosters.lite.utils.ContactsUtils;
|
||||||
|
import ru.vtosters.lite.utils.ThemesUtils;
|
||||||
|
|
||||||
public class OtherFragment extends MaterialPreferenceToolbarFragment {
|
public class OtherFragment extends MaterialPreferenceToolbarFragment {
|
||||||
private static final int VK_ADMIN_TOKEN_REQUEST_CODE = 1;
|
private static final int VK_ADMIN_TOKEN_REQUEST_CODE = 1;
|
||||||
@@ -194,88 +194,86 @@ public class OtherFragment extends MaterialPreferenceToolbarFragment {
|
|||||||
four.setChecked(val == 4);
|
four.setChecked(val == 4);
|
||||||
five.setChecked(val == 5);
|
five.setChecked(val == 5);
|
||||||
|
|
||||||
VkAlertDialog.Builder builder = new VkAlertDialog.Builder(getContext());
|
new VkAlertDialog.Builder(getContext())
|
||||||
builder.setTitle(AndroidUtils.getString("cache_clean_title"));
|
.setTitle(AndroidUtils.getString("cache_clean_title"))
|
||||||
builder.setMessage(AndroidUtils.getString("cache_select_size"));
|
.setMessage(AndroidUtils.getString("cache_select_size"))
|
||||||
builder.setCancelable(true);
|
.setCancelable(true)
|
||||||
builder.setNegativeButton(AndroidUtils.getString("cancel"), null);
|
.setNegativeButton(AndroidUtils.getString("cancel"), null)
|
||||||
builder.setView(rg);
|
.setView(rg)
|
||||||
builder.setPositiveButton(AndroidUtils.getString("save"), (dialog, which) -> {
|
.setPositiveButton(AndroidUtils.getString("save"), (dialog, which) -> {
|
||||||
var pref = getDefaultPrefs().edit();
|
var sizes = new String[] { "Default", "100mb", "500mb", "1gb", "2gb", "5gb" };
|
||||||
var checked = rg.getCheckedRadioButtonId();
|
var id = rg.getCheckedRadioButtonId();
|
||||||
|
getDefaultPrefs().edit()
|
||||||
if (checked == zero.getId()) {
|
.putInt("autoclearcache_size", id)
|
||||||
pref.putInt("autoclearcache_size", 0);
|
.putString("autoclearcache", sizes[id])
|
||||||
pref.putString("autoclearcache", "Default");
|
.apply();
|
||||||
} else if (checked == one.getId()) {
|
})
|
||||||
pref.putInt("autoclearcache_size", 1);
|
.show();
|
||||||
pref.putString("autoclearcache", "100mb");
|
|
||||||
} else if (checked == two.getId()) {
|
|
||||||
pref.putInt("autoclearcache_size", 2);
|
|
||||||
pref.putString("autoclearcache", "500mb");
|
|
||||||
} else if (checked == three.getId()) {
|
|
||||||
pref.putInt("autoclearcache_size", 3);
|
|
||||||
pref.putString("autoclearcache", "1gb");
|
|
||||||
} else if (checked == four.getId()) {
|
|
||||||
pref.putInt("autoclearcache_size", 4);
|
|
||||||
pref.putString("autoclearcache", "2gb");
|
|
||||||
} else if (checked == five.getId()) {
|
|
||||||
pref.putInt("autoclearcache_size", 5);
|
|
||||||
pref.putString("autoclearcache", "5gb");
|
|
||||||
}
|
|
||||||
|
|
||||||
pref.apply();
|
|
||||||
});
|
|
||||||
builder.show();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void cacheCleanDialog() {
|
private void cacheCleanDialog() {
|
||||||
VkAlertDialog.Builder builder = new VkAlertDialog.Builder(getContext());
|
new VkAlertDialog.Builder(getContext())
|
||||||
builder.setTitle(AndroidUtils.getString("select_which_clean"));
|
.setTitle(AndroidUtils.getString("select_which_clean"))
|
||||||
builder.setItems(AndroidUtils.getArray("cache_cleaner"), (dialog, which) -> {
|
.setItems(AndroidUtils.getArray("cache_cleaner"), (dialog, which) -> {
|
||||||
switch (which) {
|
switch (which) {
|
||||||
case 0: {
|
case 0: {
|
||||||
SharedPreferences prefs2 = getContext().getSharedPreferences("stickers_storage", Context.MODE_PRIVATE);
|
SharedPreferences prefs2 = getContext().getSharedPreferences("stickers_storage", Context.MODE_PRIVATE);
|
||||||
prefs2.edit().clear().commit();
|
prefs2.edit().clear().commit();
|
||||||
new WebView(getActivity()).clearCache(true);
|
clearWebViewCache();
|
||||||
VKImageLoader.e();
|
VKImageLoader.e();
|
||||||
ImEngineProvider.b().a();
|
ImEngineProvider.b().a();
|
||||||
ImAudioMsgPlayerProvider.b().e(PlayerActionSources.a);
|
ImAudioMsgPlayerProvider.b().e(PlayerActionSources.a);
|
||||||
ImAudioMsgPlayerProvider.b().d(PlayerActionSources.a);
|
ImAudioMsgPlayerProvider.b().d(PlayerActionSources.a);
|
||||||
FileUtils.l();
|
FileUtils.l();
|
||||||
Stickers.l.c();
|
Stickers.l.c();
|
||||||
ImEngineExt.a(ImEngine1.a());
|
ImEngineExt.a(ImEngine1.a());
|
||||||
AutoPlayCacheHolder.d.a();
|
AutoPlayCacheHolder.d.a();
|
||||||
MediaStorage.a();
|
MediaStorage.a();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 1: {
|
case 1: {
|
||||||
SharedPreferences prefs2 = getContext().getSharedPreferences("stickers_storage", Context.MODE_PRIVATE);
|
SharedPreferences prefs2 = getContext().getSharedPreferences("stickers_storage", Context.MODE_PRIVATE);
|
||||||
prefs2.edit().clear().commit();
|
prefs2.edit().clear().commit();
|
||||||
Stickers.l.c();
|
Stickers.l.c();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 2:
|
case 2:
|
||||||
VKImageLoader.e();
|
VKImageLoader.e();
|
||||||
ImEngineExt.a(ImEngine1.a());
|
ImEngineExt.a(ImEngine1.a());
|
||||||
break;
|
break;
|
||||||
case 3:
|
case 3:
|
||||||
AutoPlayCacheHolder.d.a();
|
AutoPlayCacheHolder.d.a();
|
||||||
MediaStorage.a();
|
MediaStorage.a();
|
||||||
break;
|
break;
|
||||||
case 4:
|
case 4:
|
||||||
ImEngineProvider.b().a();
|
ImEngineProvider.b().a();
|
||||||
ImAudioMsgPlayerProvider.b().e(PlayerActionSources.a);
|
ImAudioMsgPlayerProvider.b().e(PlayerActionSources.a);
|
||||||
ImAudioMsgPlayerProvider.b().d(PlayerActionSources.a);
|
ImAudioMsgPlayerProvider.b().d(PlayerActionSources.a);
|
||||||
break;
|
break;
|
||||||
case 5:
|
case 5:
|
||||||
new WebView(getActivity()).clearCache(true);
|
clearWebViewCache();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
Toast.makeText(getContext(), AndroidUtils.getString("cache_cleaned"), LENGTH_SHORT).show();
|
||||||
|
})
|
||||||
|
.show();
|
||||||
|
}
|
||||||
|
|
||||||
Toast.makeText(getContext(), AndroidUtils.getString("cache_cleaned"), LENGTH_SHORT).show();
|
private void clearWebViewCache() {
|
||||||
});
|
new WebView(requireContext()).clearCache(true);
|
||||||
builder.create().show();
|
}
|
||||||
|
|
||||||
|
private void delprefs(Context context) {
|
||||||
|
new VkAlertDialog.Builder(context)
|
||||||
|
.setTitle(AndroidUtils.getString("warning"))
|
||||||
|
.setMessage(AndroidUtils.getString("settings_reset_confirm"))
|
||||||
|
.setCancelable(false)
|
||||||
|
.setPositiveButton(AndroidUtils.getString("yes"), (dialogInterface, i) -> {
|
||||||
|
deletePrefs();
|
||||||
|
restartApplication();
|
||||||
|
})
|
||||||
|
.setNegativeButton(AndroidUtils.getString("cancel"), (dialogInterface, i) -> dialogInterface.dismiss())
|
||||||
|
.show();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class d implements Preference.OnPreferenceClickListener {
|
public static class d implements Preference.OnPreferenceClickListener {
|
||||||
@@ -286,6 +284,25 @@ public class OtherFragment extends MaterialPreferenceToolbarFragment {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static class b implements Preference.OnPreferenceClickListener {
|
||||||
|
@Override // android.support.v7.preference.Preference.c
|
||||||
|
public boolean onPreferenceClick(Preference preference) {
|
||||||
|
System.exit(0);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class saveprefs implements Preference.OnPreferenceClickListener {
|
||||||
|
saveprefs() {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override // android.support.v7.preference.Preference.c
|
||||||
|
public boolean onPreferenceClick(Preference preference) {
|
||||||
|
backupSettings();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public class onlines implements Preference.OnPreferenceClickListener {
|
public class onlines implements Preference.OnPreferenceClickListener {
|
||||||
@Override // android.support.v7.preference.Preference.c
|
@Override // android.support.v7.preference.Preference.c
|
||||||
public boolean onPreferenceClick(Preference preference) {
|
public boolean onPreferenceClick(Preference preference) {
|
||||||
@@ -298,27 +315,6 @@ public class OtherFragment extends MaterialPreferenceToolbarFragment {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class b implements Preference.OnPreferenceClickListener {
|
|
||||||
@Override // android.support.v7.preference.Preference.c
|
|
||||||
public boolean onPreferenceClick(Preference preference) {
|
|
||||||
System.exit(0);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void delprefs(Context context) {
|
|
||||||
VkAlertDialog.Builder builder = new VkAlertDialog.Builder(context);
|
|
||||||
builder.setTitle(AndroidUtils.getString("warning"));
|
|
||||||
builder.setMessage("Вы действительно хотите сбросить настройки?");
|
|
||||||
builder.setCancelable(false);
|
|
||||||
builder.setPositiveButton(AndroidUtils.getString("yes"), (dialogInterface, i) -> {
|
|
||||||
deletePrefs();
|
|
||||||
restartApplication();
|
|
||||||
});
|
|
||||||
builder.setNegativeButton(AndroidUtils.getString("cancel"), (dialogInterface, i) -> dialogInterface.dismiss());
|
|
||||||
builder.show();
|
|
||||||
}
|
|
||||||
|
|
||||||
class c implements Preference.OnPreferenceClickListener {
|
class c implements Preference.OnPreferenceClickListener {
|
||||||
public void copy(Context context, String str) {
|
public void copy(Context context, String str) {
|
||||||
((ClipboardManager) context.getSystemService(Context.CLIPBOARD_SERVICE)).setPrimaryClip(ClipData.newPlainText("MBH-ST", str));
|
((ClipboardManager) context.getSystemService(Context.CLIPBOARD_SERVICE)).setPrimaryClip(ClipData.newPlainText("MBH-ST", str));
|
||||||
@@ -349,17 +345,6 @@ public class OtherFragment extends MaterialPreferenceToolbarFragment {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class saveprefs implements Preference.OnPreferenceClickListener {
|
|
||||||
saveprefs() {
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override // android.support.v7.preference.Preference.c
|
|
||||||
public boolean onPreferenceClick(Preference preference) {
|
|
||||||
backupSettings();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public class restoreprefs implements Preference.OnPreferenceClickListener {
|
public class restoreprefs implements Preference.OnPreferenceClickListener {
|
||||||
@Override // android.support.v7.preference.Preference.c
|
@Override // android.support.v7.preference.Preference.c
|
||||||
public boolean onPreferenceClick(Preference preference) {
|
public boolean onPreferenceClick(Preference preference) {
|
||||||
@@ -375,7 +360,8 @@ public class OtherFragment extends MaterialPreferenceToolbarFragment {
|
|||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
Toast.makeText(getContext(), AndroidUtils.getString("backup_error"), LENGTH_LONG).show();
|
Toast.makeText(getContext(), AndroidUtils.getString("backup_error"), LENGTH_LONG).show();
|
||||||
}
|
}
|
||||||
}).create().show();
|
})
|
||||||
|
.show();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ package ru.vtosters.lite.ui.fragments;
|
|||||||
|
|
||||||
import static ru.vtosters.lite.utils.AndroidUtils.edit;
|
import static ru.vtosters.lite.utils.AndroidUtils.edit;
|
||||||
import static ru.vtosters.lite.utils.AndroidUtils.getIdentifier;
|
import static ru.vtosters.lite.utils.AndroidUtils.getIdentifier;
|
||||||
import static ru.vtosters.lite.utils.AndroidUtils.getPreferences;
|
|
||||||
import static ru.vtosters.lite.utils.AndroidUtils.isTablet;
|
import static ru.vtosters.lite.utils.AndroidUtils.isTablet;
|
||||||
import static ru.vtosters.lite.utils.LifecycleUtils.restartApplicationWithTimer;
|
import static ru.vtosters.lite.utils.LifecycleUtils.restartApplicationWithTimer;
|
||||||
|
|
||||||
@@ -15,8 +14,6 @@ import androidx.preference.Preference;
|
|||||||
import com.vk.navigation.Navigator;
|
import com.vk.navigation.Navigator;
|
||||||
import com.vtosters.lite.general.fragments.MaterialPreferenceToolbarFragment;
|
import com.vtosters.lite.general.fragments.MaterialPreferenceToolbarFragment;
|
||||||
|
|
||||||
import ru.vtosters.lite.utils.LifecycleUtils;
|
|
||||||
|
|
||||||
|
|
||||||
public class ThemesFragment extends MaterialPreferenceToolbarFragment {
|
public class ThemesFragment extends MaterialPreferenceToolbarFragment {
|
||||||
|
|
||||||
@@ -37,22 +34,11 @@ public class ThemesFragment extends MaterialPreferenceToolbarFragment {
|
|||||||
findPreference("dockbar_accent").setOnPreferenceClickListener(new restart());
|
findPreference("dockbar_accent").setOnPreferenceClickListener(new restart());
|
||||||
findPreference("dockcounter").setOnPreferenceClickListener(new restart());
|
findPreference("dockcounter").setOnPreferenceClickListener(new restart());
|
||||||
|
|
||||||
if (isTablet()){
|
if (isTablet()) {
|
||||||
findPreference("dockbarsett").setVisible(false);
|
findPreference("dockbarsett").setVisible(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public class openicons implements Preference.OnPreferenceClickListener {
|
|
||||||
@Override
|
|
||||||
public boolean onPreferenceClick(Preference preference) {
|
|
||||||
Context context = requireContext();
|
|
||||||
Intent a2 = new Navigator(IconsFragment.class).b(context);
|
|
||||||
a2.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
|
||||||
context.startActivity(a2);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class restart implements Preference.OnPreferenceClickListener {
|
public static class restart implements Preference.OnPreferenceClickListener {
|
||||||
@Override
|
@Override
|
||||||
public boolean onPreferenceClick(Preference preference) {
|
public boolean onPreferenceClick(Preference preference) {
|
||||||
@@ -78,4 +64,15 @@ public class ThemesFragment extends MaterialPreferenceToolbarFragment {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public class openicons implements Preference.OnPreferenceClickListener {
|
||||||
|
@Override
|
||||||
|
public boolean onPreferenceClick(Preference preference) {
|
||||||
|
Context context = requireContext();
|
||||||
|
Intent a2 = new Navigator(IconsFragment.class).b(context);
|
||||||
|
a2.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||||
|
context.startActivity(a2);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user