Compare commits

..

15 Commits

Author SHA1 Message Date
ZhanGSKen 26301c68fa <mygallery>APK 15.0.20 release Publish. 2026-08-23 08:47:32 +08:00
BigPickle 9f0d8fbffb 已置顶相册长按菜单新增“置顶”功能,支持再次置顶到最前
PinnedAlbumDbHelper 新增 repinAlbumToFront():将当前相册集
排序号置为1,其余置顶记录整体后移一位;并新增
normalizeSortOrders() 按现有顺序把所有排序号重排为连续的
1..n,修正数据库中可能出现的序号空洞或重复。
AlbumAdapter 中已置顶相册的弹出菜单扩展为「取消置顶」「置顶」
两项,点击「置顶」即重新置顶到最前并刷新列表。
2026-08-23 08:44:07 +08:00
ZhanGSKen c270ef9d1f 更新源码维护人员联系信息。 2026-08-23 08:27:02 +08:00
ZhanGSKen 3b92af52f6 <mygallery>APK 15.0.19 release Publish. 2026-08-23 08:17:44 +08:00
BigPickle 6fb6fac2ba 修复封面剪裁窗口空白的包名残留问题
模块更名为 mygallery 后,activity_crop.xml 中自定义视图
仍引用旧包 cc.winboll.studio.gallery,导致 CropActivity
布局膨胀失败、剪裁窗口显示空白。现统一更正为
cc.winboll.studio.mygallery 包名引用,并同步更新
ACTION_COVER_UPDATED 广播 action 常量。
2026-08-23 08:10:38 +08:00
ZhanGSKen 04cd87842a 更新基础类库引用 2026-08-23 07:49:39 +08:00
ZhanGSKen 1b86e70069 更新应用介绍和资源链接 2026-08-23 07:40:42 +08:00
ZhanGSKen 13f1aa9e1f 更新应用默认显示名称 2026-08-23 07:22:25 +08:00
ZhanGSKen 675fa60670 设置应用图标配置规则,区分beta图标stage图标。 2026-08-23 07:19:10 +08:00
ZhanGSKen 0383f7c72d 更新java源码应用模块文件夹名称gallery为mygallery。 2026-08-23 07:03:06 +08:00
ZhanGSKen 800ba03d0f 更新应用配置模块名称为mygallery 2026-08-23 06:57:53 +08:00
ZhanGSKen 6aa19195f6 更换应用模块gallery为mygallery 2026-08-23 06:53:40 +08:00
ZhanGSKen 3c84c8205a 添加新应用图标资源 2026-08-23 06:49:53 +08:00
ZhanGSKen 0c348db4f7 <gallery>APK 15.0.18 release Publish. 2026-07-20 19:20:48 +08:00
MiMo a9f3c9fa81 feat(gallery): 实现置顶相册排序功能
1. 数据库升级
   - PinnedAlbumDbHelper 版本升级至 2
   - 新增 sort_order 字段存储排序号
   - 自动迁移旧数据并分配排序号

2. 置顶排序逻辑
   - 新置顶相册排序号设为1,其他相册排序号+1
   - 取消置顶时,后续相册排序号自动-1
   - 使用事务确保数据一致性

3. 列表加载与刷新
   - 加载相册时按排序号由小到大排列
   - 刷新列表时保持排序号顺序显示
   - 使用 LinkedHashMap 保持插入顺序

4. 调试日志
   - 置顶操作后输出所有相册排序号
   - 取消置顶时输出原排序号

修改文件:
- PinnedAlbumDbHelper.java
- MainActivity.java
- AlbumAdapter.java
- build.properties
2026-07-20 19:15:59 +08:00
106 changed files with 365 additions and 173 deletions
@@ -1,78 +0,0 @@
package cc.winboll.studio.gallery;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import cc.winboll.studio.libappbase.LogUtils;
public class PinnedAlbumDbHelper extends SQLiteOpenHelper {
public static final String TAG = "PinnedAlbumDbHelper";
private static final String DB_NAME = "pinned_album.db";
private static final int DB_VERSION = 1;
private static final String TABLE_NAME = "pinned_albums";
private static final String COLUMN_PATH = "album_path";
private static final String SQL_CREATE = "CREATE TABLE " + TABLE_NAME + " ("
+ COLUMN_PATH + " TEXT PRIMARY KEY)";
private static PinnedAlbumDbHelper dbHelper;
public static PinnedAlbumDbHelper getInstance(Context context) {
if (dbHelper == null) {
dbHelper = new PinnedAlbumDbHelper(context.getApplicationContext());
}
return dbHelper;
}
public PinnedAlbumDbHelper(Context context) {
super(context, DB_NAME, null, DB_VERSION);
}
@Override
public void onCreate(SQLiteDatabase db) {
db.execSQL(SQL_CREATE);
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
db.execSQL("DROP TABLE IF EXISTS " + TABLE_NAME);
onCreate(db);
}
public void pinAlbum(String albumPath) {
SQLiteDatabase db = getWritableDatabase();
ContentValues values = new ContentValues();
values.put(COLUMN_PATH, albumPath);
db.insertWithOnConflict(TABLE_NAME, null, values, SQLiteDatabase.CONFLICT_IGNORE);
LogUtils.d(TAG, "pinAlbum: " + albumPath);
}
public void unpinAlbum(String albumPath) {
SQLiteDatabase db = getWritableDatabase();
db.delete(TABLE_NAME, COLUMN_PATH + " = ?", new String[]{albumPath});
LogUtils.d(TAG, "unpinAlbum: " + albumPath);
}
public boolean isPinned(String albumPath) {
SQLiteDatabase db = getReadableDatabase();
Cursor cursor = db.query(TABLE_NAME, null, COLUMN_PATH + " = ?",
new String[]{albumPath}, null, null, null);
boolean pinned = cursor.getCount() > 0;
cursor.close();
return pinned;
}
public String[] getPinnedPaths() {
SQLiteDatabase db = getReadableDatabase();
Cursor cursor = db.query(TABLE_NAME, new String[]{COLUMN_PATH}, null, null, null, null, null);
String[] paths = new String[cursor.getCount()];
int i = 0;
while (cursor.moveToNext()) {
paths[i++] = cursor.getString(0);
}
cursor.close();
return paths;
}
}
+3 -3
View File
@@ -1,7 +1,7 @@
# Gallery
# MyGallery
#### 介绍
云宝相册应用
我的相册应用
#### 软件架构
适配安卓应用 [AIDE Pro] 的 Gradle 编译结构。
@@ -18,7 +18,7 @@
1. Fork 本仓库
2. 新建 Feat_xxx 分支
3. 提交代码 : ZhanGSKen(ZhanGSKen<zhangsken@188.com>)
3. 提交代码 : ZhanGSKen(ZhanGSKen<ZhanGSKen@QQ.COM>)
4. 新建 Pull Request
@@ -23,7 +23,7 @@ android {
buildToolsVersion "30.0.3"
defaultConfig {
applicationId "cc.winboll.studio.gallery"
applicationId "cc.winboll.studio.mygallery"
minSdkVersion 26
// MIUI12
targetSdkVersion 30
@@ -108,12 +108,12 @@ dependencies {
implementation 'com.termux:termux-shared:0.118.0'
*/
// WinBoLL库 nexus.winboll.cc
api 'cc.winboll.studio:libaes:15.20.21'
api 'cc.winboll.studio:libappbase:15.20.34'
//api 'cc.winboll.studio:libaes:15.20.21'
//api 'cc.winboll.studio:libappbase:15.20.34'
// WinBoLL备用库 jitpack.io
//api 'com.github.ZhanGSKen:AES:aes-v15.15.7'
//api 'com.github.ZhanGSKen:APPBase:appbase-v15.15.4'
// jitpack.io
api 'com.github.ZhanGSKen:libappbase:appbase-v15.21.+'
api 'com.github.ZhanGSKen:libaes:aes-v15.21.+'
api fileTree(dir: 'libs', include: ['*.jar'])
}
@@ -1,8 +1,8 @@
#Created by .winboll/winboll_app_build.gradle
#Sun Jul 19 15:10:49 HKT 2026
stageCount=18
#Sun Aug 23 08:47:32 HKT 2026
stageCount=21
libraryProject=
baseVersion=15.0
publishVersion=15.0.17
publishVersion=15.0.20
buildCount=0
baseBetaVersion=15.0.18
baseBetaVersion=15.0.21
@@ -2,7 +2,8 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools" >
<application>
<application tools:replace="android:icon"
android:icon="@drawable/ic_my_gallery_beta">
<!-- Put flavor specific code here -->
@@ -2,5 +2,5 @@
<resources>
<!-- Put flavor specific strings here -->
<string name="app_name">Gallery+</string>
<string name="app_name">MyGallery+</string>
</resources>
@@ -1,7 +1,7 @@
<?xml version='1.0' encoding='utf-8'?>
<manifest
xmlns:android="http://schemas.android.com/apk/res/android"
package="cc.winboll.studio.gallery">
package="cc.winboll.studio.mygallery">
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
@@ -9,8 +9,8 @@
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:roundIcon="@mipmap/ic_launcher_round"
android:icon="@drawable/ic_my_gallery"
android:roundIcon="@drawable/ic_my_gallery"
android:label="@string/app_name"
android:theme="@style/GalleryTheme"
android:resizeableActivity="true"
@@ -1,4 +1,4 @@
package cc.winboll.studio.gallery;
package cc.winboll.studio.mygallery;
import android.os.Bundle;
import android.view.View;
@@ -33,18 +33,18 @@ public class AboutActivity extends AppCompatActivity {
private APPInfo genDefaultAppInfo() {
LogUtils.d(TAG, "genDefaultAppInfo() 调用");
String branchName = "gallery";
String branchName = "mygallery";
APPInfo appInfo = new APPInfo();
appInfo.setAppName("Gallery");
appInfo.setAppName("MyGallery");
appInfo.setAppIcon(R.drawable.ic_winboll);
appInfo.setAppDescription(getString(R.string.app_description));
appInfo.setAppGitName("Gallery");
appInfo.setAppGitName("MyGallery");
appInfo.setAppGitOwner("ZhanGSKen");
appInfo.setAppGitAPPBranch(branchName);
appInfo.setAppGitAPPSubProjectFolder(branchName);
appInfo.setAppHomePage("https://www.winboll.cc/apks/index.php?project=Gallery");
appInfo.setAppAPKName("Gallery");
appInfo.setAppAPKFolderName("Gallery");
appInfo.setAppHomePage("https://www.winboll.cc/apks/index.php?project=MyGallery");
appInfo.setAppAPKName("MyGallery");
appInfo.setAppAPKFolderName("MyGallery");
LogUtils.d(TAG, "genDefaultAppInfo: 应用信息已生成");
return appInfo;
}
@@ -1,4 +1,4 @@
package cc.winboll.studio.gallery;
package cc.winboll.studio.mygallery;
import android.net.Uri;
import cc.winboll.studio.libappbase.LogUtils;
@@ -22,4 +22,4 @@ public class Album {
public String getPath() { return path; }
public Uri getCoverUri() { return coverUri; }
public int getImageCount() { return imageCount; }
}
}
@@ -1,4 +1,4 @@
package cc.winboll.studio.gallery;
package cc.winboll.studio.mygallery;
import android.content.ContentResolver;
import android.content.Intent;
@@ -21,7 +21,7 @@ import com.google.android.material.floatingactionbutton.FloatingActionButton;
import java.util.ArrayList;
import cc.winboll.studio.libappbase.LogUtils;
import cc.winboll.studio.gallery.ImageAdapter.OnImageClickListener;
import cc.winboll.studio.mygallery.ImageAdapter.OnImageClickListener;
public class AlbumActivity extends AppCompatActivity {
public static final String TAG = "AlbumActivity";
@@ -248,4 +248,4 @@ private String getSortOrder(int sortMode) {
loadImages();
}
}
}
}
@@ -1,4 +1,4 @@
package cc.winboll.studio.gallery;
package cc.winboll.studio.mygallery;
import android.net.Uri;
import android.view.LayoutInflater;
@@ -86,17 +86,28 @@ public class AlbumAdapter extends RecyclerView.Adapter<AlbumAdapter.ViewHolder>
public void refreshPinned() {
if (pinnedDbHelper != null && albums != null && !albums.isEmpty()) {
Set<String> pinnedPaths = new HashSet<String>();
pinnedPaths.addAll(Arrays.asList(pinnedDbHelper.getPinnedPaths()));
java.util.LinkedHashMap<String, Integer> pinnedPathMap = pinnedDbHelper.getPinnedPathsWithSortOrder();
Set<String> pinnedPaths = pinnedPathMap.keySet();
ArrayList<Album> pinned = new ArrayList<Album>();
ArrayList<Album> unpinned = new ArrayList<Album>();
// 按照排序号顺序添加置顶相册
for (String pinnedPath : pinnedPathMap.keySet()) {
for (Album album : albums) {
if (album.getPath().equals(pinnedPath)) {
pinned.add(album);
break;
}
}
}
// 添加非置顶相册
for (Album album : albums) {
if (pinnedPaths.contains(album.getPath())) {
pinned.add(album);
} else {
if (!pinnedPaths.contains(album.getPath())) {
unpinned.add(album);
}
}
albums.clear();
albums.addAll(pinned);
albums.addAll(unpinned);
@@ -108,7 +119,12 @@ private void showContextMenu(View view, final Album album) {
android.app.AlertDialog.Builder builder = new android.app.AlertDialog.Builder(view.getContext());
builder.setTitle(album.getName());
final boolean isPinned = pinnedDbHelper != null && pinnedDbHelper.isPinned(album.getPath());
String[] items = isPinned ? new String[]{"取消置顶"} : new String[]{"置顶"};
String[] items = null;
if (isPinned) {
items = new String[]{"取消置顶", "置顶"};
} else {
items = new String[]{"置顶"};
}
builder.setItems(items, new android.content.DialogInterface.OnClickListener() {
@Override
public void onClick(android.content.DialogInterface dialog, int which) {
@@ -119,8 +135,10 @@ private void showContextMenu(View view, final Album album) {
} else {
pinnedDbHelper.pinAlbum(album.getPath());
}
refreshPinned();
} else if (which == 1 && isPinned) {
pinnedDbHelper.repinAlbumToFront(album.getPath());
}
refreshPinned();
}
}
});
@@ -1,4 +1,4 @@
package cc.winboll.studio.gallery;
package cc.winboll.studio.mygallery;
import android.content.ContentValues;
import android.content.Context;
@@ -128,4 +128,4 @@ public class AlbumCoverDbHelper extends SQLiteOpenHelper {
db.delete(TABLE_NAME, COLUMN_ALBUM_PATH + " = ?", new String[]{albumPath});
LogUtils.d(TAG, "deleteCover: " + albumPath);
}
}
}
@@ -1,6 +1,6 @@
package cc.winboll.studio.gallery;
package cc.winboll.studio.mygallery;
import cc.winboll.studio.gallery.utils.BackgroundUtils;
import cc.winboll.studio.mygallery.utils.BackgroundUtils;
import cc.winboll.studio.libaes.utils.WinBoLLActivityManager;
import cc.winboll.studio.libappbase.CrashActivity;
import cc.winboll.studio.libappbase.GlobalApplication;
@@ -1,4 +1,4 @@
package cc.winboll.studio.gallery;
package cc.winboll.studio.mygallery;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
@@ -1,4 +1,4 @@
package cc.winboll.studio.gallery;
package cc.winboll.studio.mygallery;
import android.content.Context;
import android.graphics.Bitmap;
@@ -747,4 +747,4 @@ public class CropCanvasView extends View {
public int getColorAt(float x, float y) {
return getImageColorAt(x, y);
}
}
}
@@ -1,4 +1,4 @@
package cc.winboll.studio.gallery;
package cc.winboll.studio.mygallery;
import android.content.Context;
import android.graphics.Canvas;
@@ -221,4 +221,4 @@ public class CropOverlayView extends View {
}
return -1;
}
}
}
@@ -1,4 +1,4 @@
package cc.winboll.studio.gallery;
package cc.winboll.studio.mygallery;
import android.content.DialogInterface;
import android.content.Intent;
@@ -1,4 +1,4 @@
package cc.winboll.studio.gallery;
package cc.winboll.studio.mygallery;
import android.net.Uri;
import android.view.LayoutInflater;
@@ -54,4 +54,4 @@ public class ImagePagerAdapter extends PagerAdapter {
public boolean isViewFromObject(@NonNull View view, @NonNull Object object) {
return view == object;
}
}
}
@@ -1,4 +1,4 @@
package cc.winboll.studio.gallery;
package cc.winboll.studio.mygallery;
import android.app.Activity;
import android.app.AlertDialog;
@@ -394,4 +394,4 @@ public class ImageViewerActivity extends Activity implements ViewPager.OnPageCha
public void onBackPressed() {
finish();
}
}
}
@@ -1,4 +1,4 @@
package cc.winboll.studio.gallery;
package cc.winboll.studio.mygallery;
import android.Manifest;
import android.content.BroadcastReceiver;
@@ -28,9 +28,9 @@ import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;
import androidx.recyclerview.widget.GridLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import cc.winboll.studio.gallery.AlbumAdapter.OnAlbumClickListener;
import cc.winboll.studio.gallery.App;
import cc.winboll.studio.gallery.utils.BackgroundUtils;
import cc.winboll.studio.mygallery.AlbumAdapter.OnAlbumClickListener;
import cc.winboll.studio.mygallery.App;
import cc.winboll.studio.mygallery.utils.BackgroundUtils;
import cc.winboll.studio.libappbase.LogActivity;
import cc.winboll.studio.libappbase.LogUtils;
import cc.winboll.studio.libappbase.ToastUtils;
@@ -216,9 +216,9 @@ public class MainActivity extends AppCompatActivity {
AlbumCoverDbHelper coverDbHelper = AlbumCoverDbHelper.getInstance(this);
PinnedAlbumDbHelper pinnedDbHelper = PinnedAlbumDbHelper.getInstance(this);
Set<String> pinnedPaths = new HashSet<String>();
String[] pinnedArray = pinnedDbHelper.getPinnedPaths();
pinnedPaths.addAll(Arrays.asList(pinnedArray));
// 获取带排序号的置顶路径映射已按排序号排序
java.util.LinkedHashMap<String, Integer> pinnedPathMap = pinnedDbHelper.getPinnedPathsWithSortOrder();
Set<String> pinnedPaths = pinnedPathMap.keySet();
ArrayList<Album> albums = new ArrayList<Album>();
@@ -252,15 +252,27 @@ public class MainActivity extends AppCompatActivity {
}
}
// 按照排序号顺序添加置顶相册
ArrayList<Album> pinned = new ArrayList<Album>();
ArrayList<Album> unpinned = new ArrayList<Album>();
// 先按照pinnedPathMap的顺序排序号顺序添加置顶相册
for (String pinnedPath : pinnedPathMap.keySet()) {
for (Album album : albums) {
if (album.getPath().equals(pinnedPath)) {
pinned.add(album);
break;
}
}
}
// 添加非置顶相册
for (Album album : albums) {
if (pinnedPaths.contains(album.getPath())) {
pinned.add(album);
} else {
if (!pinnedPaths.contains(album.getPath())) {
unpinned.add(album);
}
}
pinned.addAll(unpinned);
return pinned;
}
@@ -0,0 +1,218 @@
package cc.winboll.studio.mygallery;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import cc.winboll.studio.libappbase.LogUtils;
import java.util.LinkedHashMap;
public class PinnedAlbumDbHelper extends SQLiteOpenHelper {
public static final String TAG = "PinnedAlbumDbHelper";
private static final String DB_NAME = "pinned_album.db";
private static final int DB_VERSION = 2;
private static final String TABLE_NAME = "pinned_albums";
private static final String COLUMN_PATH = "album_path";
private static final String COLUMN_SORT_ORDER = "sort_order";
private static final String SQL_CREATE = "CREATE TABLE " + TABLE_NAME + " ("
+ COLUMN_PATH + " TEXT PRIMARY KEY, "
+ COLUMN_SORT_ORDER + " INTEGER DEFAULT 0)";
private static PinnedAlbumDbHelper dbHelper;
public static PinnedAlbumDbHelper getInstance(Context context) {
if (dbHelper == null) {
dbHelper = new PinnedAlbumDbHelper(context.getApplicationContext());
}
return dbHelper;
}
public PinnedAlbumDbHelper(Context context) {
super(context, DB_NAME, null, DB_VERSION);
}
@Override
public void onCreate(SQLiteDatabase db) {
db.execSQL(SQL_CREATE);
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
if (oldVersion < 2) {
// 创建新表
db.execSQL("DROP TABLE IF EXISTS " + TABLE_NAME + "_new");
db.execSQL("CREATE TABLE " + TABLE_NAME + "_new ("
+ COLUMN_PATH + " TEXT PRIMARY KEY, "
+ COLUMN_SORT_ORDER + " INTEGER DEFAULT 0)");
// 迁移旧数据,为现有记录分配排序号(按原始顺序)
Cursor cursor = db.query(TABLE_NAME, new String[]{COLUMN_PATH}, null, null, null, null, null);
int sortOrder = 1;
while (cursor.moveToNext()) {
String path = cursor.getString(0);
ContentValues values = new ContentValues();
values.put(COLUMN_PATH, path);
values.put(COLUMN_SORT_ORDER, sortOrder++);
db.insert(TABLE_NAME + "_new", null, values);
}
cursor.close();
// 删除旧表,重命名新表
db.execSQL("DROP TABLE IF EXISTS " + TABLE_NAME);
db.execSQL("ALTER TABLE " + TABLE_NAME + "_new RENAME TO " + TABLE_NAME);
}
}
public void pinAlbum(String albumPath) {
SQLiteDatabase db = getWritableDatabase();
db.beginTransaction();
try {
// 将所有现有置顶数据的排序号加1
db.execSQL("UPDATE " + TABLE_NAME + " SET " + COLUMN_SORT_ORDER + " = " + COLUMN_SORT_ORDER + " + 1");
// 插入新数据,排序号为1
ContentValues insertValues = new ContentValues();
insertValues.put(COLUMN_PATH, albumPath);
insertValues.put(COLUMN_SORT_ORDER, 1);
db.insertWithOnConflict(TABLE_NAME, null, insertValues, SQLiteDatabase.CONFLICT_REPLACE);
db.setTransactionSuccessful();
// 查询所有置顶相册的排序号并输出调试信息
Cursor cursor = db.query(TABLE_NAME, new String[]{COLUMN_PATH, COLUMN_SORT_ORDER},
null, null, null, null, COLUMN_SORT_ORDER + " ASC");
StringBuilder sb = new StringBuilder("All pinned albums after pin:\n");
while (cursor.moveToNext()) {
String path = cursor.getString(0);
int sortOrder = cursor.getInt(1);
sb.append(" [").append(sortOrder).append("] ").append(path).append("\n");
}
cursor.close();
LogUtils.d(TAG, sb.toString());
} finally {
db.endTransaction();
}
}
public void unpinAlbum(String albumPath) {
SQLiteDatabase db = getWritableDatabase();
db.beginTransaction();
try {
// 获取要取消置顶的相册的排序号
Cursor cursor = db.query(TABLE_NAME, new String[]{COLUMN_SORT_ORDER},
COLUMN_PATH + " = ?", new String[]{albumPath}, null, null, null);
if (cursor.moveToFirst()) {
int sortNumber = cursor.getInt(0);
cursor.close();
// 将排序号大于该排序号的记录减1
db.execSQL("UPDATE " + TABLE_NAME + " SET " + COLUMN_SORT_ORDER + " = " + COLUMN_SORT_ORDER + " - 1 WHERE " + COLUMN_SORT_ORDER + " > ?", new Object[]{sortNumber});
// 删除该相册的置顶记录
db.delete(TABLE_NAME, COLUMN_PATH + " = ?", new String[]{albumPath});
LogUtils.d(TAG, "unpinAlbum: " + albumPath + ", sort number was: " + sortNumber);
} else {
cursor.close();
}
db.setTransactionSuccessful();
} finally {
db.endTransaction();
}
}
public void repinAlbumToFront(String albumPath) {
SQLiteDatabase db = getWritableDatabase();
db.beginTransaction();
try {
// 获取要再次置顶的相册的排序号
Cursor cursor = db.query(TABLE_NAME, new String[]{COLUMN_SORT_ORDER},
COLUMN_PATH + " = ?", new String[]{albumPath}, null, null, null);
if (cursor.moveToFirst()) {
int sortNumber = cursor.getInt(0);
cursor.close();
if (sortNumber > 1) {
// 将排序号小于该记录的记录全部加1(整体后移)
db.execSQL("UPDATE " + TABLE_NAME + " SET " + COLUMN_SORT_ORDER + " = " + COLUMN_SORT_ORDER + " + 1 WHERE " + COLUMN_SORT_ORDER + " < ?", new Object[]{sortNumber});
// 该相册置顶到排序号1
ContentValues values = new ContentValues();
values.put(COLUMN_SORT_ORDER, 1);
db.update(TABLE_NAME, values, COLUMN_PATH + " = ?", new String[]{albumPath});
LogUtils.d(TAG, "repinAlbumToFront: " + albumPath + ", sort number was: " + sortNumber);
}
// 按当前顺序将排序号重排为连续的1..n
normalizeSortOrders(db);
// 查询所有置顶相册的排序号并输出调试信息
Cursor debugCursor = db.query(TABLE_NAME, new String[]{COLUMN_PATH, COLUMN_SORT_ORDER},
null, null, null, null, COLUMN_SORT_ORDER + " ASC");
StringBuilder sb = new StringBuilder("All pinned albums after repin:\n");
while (debugCursor.moveToNext()) {
sb.append(" [").append(debugCursor.getInt(1)).append("] ").append(debugCursor.getString(0)).append("\n");
}
debugCursor.close();
LogUtils.d(TAG, sb.toString());
} else {
cursor.close();
}
db.setTransactionSuccessful();
} finally {
db.endTransaction();
}
}
// 按排序号升序将所有记录重排为连续的1..n,修正可能出现的序号空洞或重复
private void normalizeSortOrders(SQLiteDatabase db) {
Cursor cursor = db.query(TABLE_NAME, new String[]{COLUMN_PATH}, null, null, null, null,
COLUMN_SORT_ORDER + " ASC");
int sortOrder = 1;
while (cursor.moveToNext()) {
String path = cursor.getString(0);
db.execSQL("UPDATE " + TABLE_NAME + " SET " + COLUMN_SORT_ORDER + " = ? WHERE " + COLUMN_PATH + " = ?",
new Object[]{sortOrder++, path});
}
cursor.close();
}
public boolean isPinned(String albumPath) {
SQLiteDatabase db = getReadableDatabase();
Cursor cursor = db.query(TABLE_NAME, null, COLUMN_PATH + " = ?",
new String[]{albumPath}, null, null, null);
boolean pinned = cursor.getCount() > 0;
cursor.close();
return pinned;
}
public String[] getPinnedPaths() {
SQLiteDatabase db = getReadableDatabase();
Cursor cursor = db.query(TABLE_NAME, new String[]{COLUMN_PATH}, null, null, null, null,
COLUMN_SORT_ORDER + " ASC");
String[] paths = new String[cursor.getCount()];
int i = 0;
while (cursor.moveToNext()) {
paths[i++] = cursor.getString(0);
}
cursor.close();
return paths;
}
public LinkedHashMap<String, Integer> getPinnedPathsWithSortOrder() {
SQLiteDatabase db = getReadableDatabase();
Cursor cursor = db.query(TABLE_NAME, new String[]{COLUMN_PATH, COLUMN_SORT_ORDER},
null, null, null, null, COLUMN_SORT_ORDER + " ASC");
LinkedHashMap<String, Integer> map = new LinkedHashMap<String, Integer>();
while (cursor.moveToNext()) {
String path = cursor.getString(0);
int sortOrder = cursor.getInt(1);
map.put(path, sortOrder);
}
cursor.close();
return map;
}
}
@@ -1,4 +1,4 @@
package cc.winboll.studio.gallery;
package cc.winboll.studio.mygallery;
import android.content.ContentValues;
import android.content.Context;
@@ -75,4 +75,4 @@ public class PinnedImageDbHelper extends SQLiteOpenHelper {
cursor.close();
return paths;
}
}
}
@@ -1,4 +1,4 @@
package cc.winboll.studio.gallery;
package cc.winboll.studio.mygallery;
import android.content.Context;
import android.content.SharedPreferences;
@@ -14,7 +14,7 @@ public class Preferences {
private static final String KEY_COVER_HEIGHT = "cover_height";
private static final String KEY_COVER_RATIO = "cover_ratio";
public static final String ACTION_COVER_UPDATED = "cc.winboll.studio.gallery.COVER_UPDATED";
public static final String ACTION_COVER_UPDATED = "cc.winboll.studio.mygallery.COVER_UPDATED";
private static final int DEFAULT_BG_TYPE = 0;
private static final int DEFAULT_SORT_MODE = 0;
@@ -90,4 +90,4 @@ public class Preferences {
public void setCoverRatio(float ratio) {
prefs.edit().putFloat(KEY_COVER_RATIO, ratio).apply();
}
}
}
@@ -1,4 +1,4 @@
package cc.winboll.studio.gallery;
package cc.winboll.studio.mygallery;
import android.os.Bundle;
import android.view.View;
@@ -43,4 +43,4 @@ public class SettingsActivity extends AppCompatActivity {
}
});
}
}
}
@@ -1,4 +1,4 @@
package cc.winboll.studio.gallery;
package cc.winboll.studio.mygallery;
import android.content.ContentResolver;
import android.content.Intent;
@@ -190,4 +190,4 @@ public class TrashActivity extends AppCompatActivity {
public String originalPath;
public String originalFolder;
}
}
}
@@ -1,4 +1,4 @@
package cc.winboll.studio.gallery;
package cc.winboll.studio.mygallery;
import android.net.Uri;
import android.view.LayoutInflater;
@@ -108,4 +108,4 @@ public class TrashAdapter extends RecyclerView.Adapter<TrashAdapter.ViewHolder>
btnDelete = itemView.findViewById(R.id.btn_delete);
}
}
}
}
@@ -1,4 +1,4 @@
package cc.winboll.studio.gallery;
package cc.winboll.studio.mygallery;
import android.content.ContentValues;
import android.content.Context;
@@ -75,4 +75,4 @@ public class TrashDbHelper extends SQLiteOpenHelper {
}
return trashDir.getAbsolutePath();
}
}
}
@@ -1,4 +1,4 @@
package cc.winboll.studio.gallery;
package cc.winboll.studio.mygallery;
import android.content.ContentResolver;
import android.content.Context;
@@ -155,4 +155,4 @@ public class TrashManager {
}
});
}
}
}
@@ -1,4 +1,4 @@
package cc.winboll.studio.gallery;
package cc.winboll.studio.mygallery;
import android.content.Context;
import android.graphics.Canvas;
@@ -166,4 +166,4 @@ public class ZoomContainerView extends FrameLayout {
}
return handled || super.onTouchEvent(event);
}
}
}
@@ -1,4 +1,4 @@
package cc.winboll.studio.gallery.dialog;
package cc.winboll.studio.mygallery.dialog;
import android.app.Dialog;
import android.content.Context;
@@ -6,7 +6,7 @@ import android.os.Bundle;
import android.view.WindowManager;
import android.widget.TextView;
import androidx.annotation.NonNull;
import cc.winboll.studio.gallery.R;
import cc.winboll.studio.mygallery.R;
/**
* 颜色表对话框
@@ -1,4 +1,4 @@
package cc.winboll.studio.gallery.utils;
package cc.winboll.studio.mygallery.utils;
import android.content.Context;
import android.content.SharedPreferences;
@@ -1,4 +1,4 @@
package cc.winboll.studio.gallery.utils;
package cc.winboll.studio.mygallery.utils;
import android.content.Context;
import android.content.SharedPreferences;
@@ -1,4 +1,4 @@
package cc.winboll.studio.gallery.views;
package cc.winboll.studio.mygallery.views;
import android.content.Context;
import android.util.AttributeSet;
@@ -1,4 +1,4 @@
package cc.winboll.studio.gallery.views;
package cc.winboll.studio.mygallery.views;
import android.content.Context;
import android.graphics.drawable.ColorDrawable;
@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android"
android:clickable="true">
<item
android:left="0dp"
android:top="0dp"
android:right="0dp"
android:bottom="0dp"
android:drawable="@drawable/my_gallery_blankbackground"/>
</layer-list>
@@ -0,0 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android"
android:clickable="true">
<item android:drawable="@drawable/ic_launcher_background"/>
<item
android:left="0dp"
android:top="0dp"
android:right="0dp"
android:bottom="0dp"
android:drawable="@drawable/my_gallery_blankbackground"/>
</layer-list>

Before

Width:  |  Height:  |  Size: 1.7 MiB

After

Width:  |  Height:  |  Size: 1.7 MiB

Before

Width:  |  Height:  |  Size: 1.2 MiB

After

Width:  |  Height:  |  Size: 1.2 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 MiB

@@ -73,19 +73,19 @@
android:layout_marginBottom="56dp"
android:fillViewport="true">
<cc.winboll.studio.gallery.ZoomContainerView
<cc.winboll.studio.mygallery.ZoomContainerView
android:id="@+id/zoom_container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center">
<cc.winboll.studio.gallery.CropCanvasView
<cc.winboll.studio.mygallery.CropCanvasView
android:id="@+id/crop_canvas_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"/>
</cc.winboll.studio.gallery.ZoomContainerView>
</cc.winboll.studio.mygallery.ZoomContainerView>
</ScrollView>

Before

Width:  |  Height:  |  Size: 3.0 KiB

After

Width:  |  Height:  |  Size: 3.0 KiB

Before

Width:  |  Height:  |  Size: 4.9 KiB

After

Width:  |  Height:  |  Size: 4.9 KiB

Before

Width:  |  Height:  |  Size: 2.0 KiB

After

Width:  |  Height:  |  Size: 2.0 KiB

Before

Width:  |  Height:  |  Size: 2.8 KiB

After

Width:  |  Height:  |  Size: 2.8 KiB

Before

Width:  |  Height:  |  Size: 4.5 KiB

After

Width:  |  Height:  |  Size: 4.5 KiB

Before

Width:  |  Height:  |  Size: 6.9 KiB

After

Width:  |  Height:  |  Size: 6.9 KiB

Before

Width:  |  Height:  |  Size: 6.3 KiB

After

Width:  |  Height:  |  Size: 6.3 KiB

Before

Width:  |  Height:  |  Size: 10 KiB

After

Width:  |  Height:  |  Size: 10 KiB

Before

Width:  |  Height:  |  Size: 9.0 KiB

After

Width:  |  Height:  |  Size: 9.0 KiB

Before

Width:  |  Height:  |  Size: 15 KiB

After

Width:  |  Height:  |  Size: 15 KiB

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