Merge branch 'master' of https://bdgit.educoder.net/p7tupf26b/git into merge-branch

pull/19/head
包尔俊 1 month ago
commit ce1ba3055d

@ -1,7 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="$PROJECT_DIR$/../.." vcs="Git" />
<mapping directory="$PROJECT_DIR$" vcs="Git" />
</component>
</project>

@ -1,28 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>app</name>
<comment>Project app created by Buildship.</comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.buildship.core.gradleprojectbuilder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.buildship.core.gradleprojectnature</nature>
</natures>
<filteredResources>
<filter>
<id>1768961338889</id>
<name></name>
<type>30</type>
<matcher>
<id>org.eclipse.core.resources.regexFilterMatcher</id>
<arguments>node_modules|\.git|__CREATED_BY_JAVA_LANGUAGE_SERVER__</arguments>
</matcher>
</filter>
</filteredResources>
</projectDescription>

@ -56,9 +56,9 @@ dependencies {
// "exclude" to listOf("")
// )))
//修改为如下代码:
implementation(files("D:\\ke\\software_enginering\\httpcomponents-client-4.5.14-bin\\lib\\httpclient-osgi-4.5.14.jar"))
implementation(files("D:\\ke\\software_enginering\\httpcomponents-client-4.5.14-bin\\lib\\httpclient-win-4.5.14.jar"))
implementation(files("D:\\ke\\software_enginering\\httpcomponents-client-4.5.14-bin\\lib\\httpcore-4.4.16.jar"))
implementation(files("D:\\college\\studying\\studying\\2025.09\\SE\\android\\client\\lib\\httpclient-osgi-4.5.14.jar"))
implementation(files("D:\\college\\studying\\studying\\2025.09\\SE\\android\\client\\lib\\httpclient-win-4.5.14.jar"))
implementation(files("D:\\college\\studying\\studying\\2025.09\\SE\\android\\client\\lib\\httpcore-4.4.16.jar"))
testImplementation(libs.junit)
androidTestImplementation(libs.ext.junit)
androidTestImplementation(libs.espresso.core)

@ -247,6 +247,12 @@ public class Notes {
* <P> Type : INTEGER </P>
*/
public static final String LOCKED = "locked";
/**
* Note's title
* <P> Type : TEXT </P>
*/
public static final String TITLE = "title";
}
public interface DataColumns {

@ -66,11 +66,11 @@ public class NotesDatabaseHelper extends SQLiteOpenHelper {
/**
*
* <p>
* 5
* 8
* onUpgrade
* </p>
*/
private static final int DB_VERSION = 5;
private static final int DB_VERSION = 8;
/**
*
@ -155,7 +155,8 @@ public class NotesDatabaseHelper extends SQLiteOpenHelper {
NoteColumns.GTASK_ID + " TEXT NOT NULL DEFAULT ''," +
NoteColumns.VERSION + " INTEGER NOT NULL DEFAULT 0," +
NoteColumns.TOP + " INTEGER NOT NULL DEFAULT 0," +
NoteColumns.LOCKED + " INTEGER NOT NULL DEFAULT 0" +
NoteColumns.LOCKED + " INTEGER NOT NULL DEFAULT 0," +
NoteColumns.TITLE + " TEXT NOT NULL DEFAULT ''" +
")";
/**
@ -511,51 +512,51 @@ public class NotesDatabaseHelper extends SQLiteOpenHelper {
boolean reCreateTriggers = false;
boolean skipV2 = false;
// 使用 while 循环逐步升级到目标版本
while (oldVersion < newVersion) {
switch (oldVersion) {
case 1:
// 从V1升级到V2包括V2到V3
upgradeToV2(db);
skipV2 = true;
oldVersion = 2;
break;
case 2:
// 从V2升级到V3如果未被V2升级包含
if (!skipV2) {
upgradeToV3(db);
reCreateTriggers = true;
}
oldVersion = 3;
break;
case 3:
// 从V3升级到V4
upgradeToV4(db);
oldVersion = 4;
break;
case 4:
// 从V4升级到V5
upgradeToV5(db);
oldVersion = 5;
break;
case 5:
// 从V5升级到V6仅在需要时
if (newVersion > 5) {
upgradeToV6(db);
}
oldVersion = 6;
break;
default:
// 如果遇到未知版本,直接跳到目标版本
Log.w(TAG, "Unknown database version: " + oldVersion + ", skipping to " + newVersion);
oldVersion = newVersion;
break;
}
// 从V1升级到V2包括V2到V3
if (oldVersion == 1) {
upgradeToV2(db);
skipV2 = true; // this upgrade including the upgrade from v2 to v3
oldVersion++;
}
// 从V2升级到V3
if (oldVersion == 2 && !skipV2) {
upgradeToV3(db);
reCreateTriggers = true;
oldVersion++;
}
// 从V3升级到V4
if (oldVersion == 3) {
upgradeToV4(db);
oldVersion++;
}
// 从V4升级到V5
if (oldVersion == 4) {
upgradeToV5(db);
oldVersion++;
}
// 兼容性处理:如果 oldVersion 为 5但 newVersion >= 7
// 说明可能跳过了 V6 的升级逻辑V6 可能在某个中间版本被合并或跳过),
// 或者用户是从一个中间状态升级上来的。
// 为了确保连贯性,我们显式检查并处理 V5 -> V6 的过渡
if (oldVersion == 5) {
upgradeToV6(db);
oldVersion++;
}
// 从V6升级到V7
if (oldVersion == 6) {
upgradeToV7(db);
oldVersion++;
}
// 从V7升级到V8
if (oldVersion == 7) {
upgradeToV8(db);
oldVersion++;
}
// 如果需要,重新创建触发器
@ -565,9 +566,33 @@ public class NotesDatabaseHelper extends SQLiteOpenHelper {
}
// 检查升级是否成功
if (oldVersion != newVersion) {
throw new IllegalStateException("Upgrade notes database to version " + newVersion
+ " fails. Current version: " + oldVersion);
// 注意由于我们可能执行了多个升级步骤oldVersion应该已经递增到了newVersion
// 但是如果newVersion比当前支持的最大版本还高oldVersion可能赶不上
// 这里放宽检查条件只要oldVersion有增加就认为是成功的
// 或者简单地只在目标版本就是DB_VERSION时进行严格检查
if (oldVersion != newVersion && newVersion <= DB_VERSION) {
// 临时注释掉这个异常抛出,允许部分升级成功的情况,
// 或者因为我们手动处理了 oldVersion++,可能逻辑上已经到达了 newVersion
// 但如果用户跨版本升级例如从V1直接到V8中间步骤都会执行
// 如果升级后的版本不等于目标版本,这确实是个问题。
// 但对于V7->V8如果oldVersion变成了8newVersion也是8则通过。
// 错误日志显示 "Upgrade notes database to version 8 fails",说明 oldVersion != newVersion
// 这意味着 oldVersion 没有正确递增到 8。
// 让我们检查一下逻辑:
// 如果初始 oldVersion = 7, newVersion = 8
// 进入 if (oldVersion == 7) 块 -> upgradeToV8 -> oldVersion 变为 8
// 此时 oldVersion (8) == newVersion (8),检查通过。
// 如果错误发生,可能是 oldVersion 初始值不是 7
// 或者前面的升级步骤有遗漏?
// 为了稳健性,我们在这里记录日志而不是直接崩溃,或者重新检查逻辑。
Log.e(TAG, "Upgrade notes database mismatch: oldVersion=" + oldVersion + ", newVersion=" + newVersion);
// 暂时抛出异常以保持原行为,但添加更多调试信息
throw new IllegalStateException("Upgrade notes database to version " + newVersion
+ " fails. Final oldVersion=" + oldVersion);
}
}
@ -591,6 +616,24 @@ public class NotesDatabaseHelper extends SQLiteOpenHelper {
+ " INTEGER NOT NULL DEFAULT 0");
Log.i(TAG, "Fixed: Added missing LOCKED column in onOpen");
}
// Check for missing TITLE column
boolean hasTitleColumn = false;
if (cursor != null) {
if (cursor.getColumnIndex(NoteColumns.TITLE) != -1) {
hasTitleColumn = true;
}
}
if (!hasTitleColumn) {
db.execSQL("ALTER TABLE " + TABLE.NOTE + " ADD COLUMN " + NoteColumns.TITLE
+ " TEXT NOT NULL DEFAULT ''");
Log.i(TAG, "Fixed: Added missing TITLE column in onOpen");
}
if (cursor != null) {
cursor.close();
}
} catch (Exception e) {
Log.e(TAG, "Failed to fix database in onOpen", e);
}
@ -700,4 +743,21 @@ public class NotesDatabaseHelper extends SQLiteOpenHelper {
Log.e(TAG, "Failed to add LOCKED column in V7 upgrade (it probably already exists)", e);
}
}
/**
* V8
* <p>
* TITLEnote
* </p>
*
* @param db SQLiteDatabase
*/
private void upgradeToV8(SQLiteDatabase db) {
try {
db.execSQL("ALTER TABLE " + TABLE.NOTE + " ADD COLUMN " + NoteColumns.TITLE
+ " TEXT NOT NULL DEFAULT ''");
} catch (Exception e) {
Log.e(TAG, "Failed to add TITLE column in V8 upgrade (it probably already exists)", e);
}
}
}

@ -131,8 +131,23 @@ public class NotesRepository {
private NoteInfo noteFromCursor(Cursor cursor) {
NoteInfo noteInfo = new NoteInfo();
noteInfo.id = cursor.getLong(cursor.getColumnIndexOrThrow(NoteColumns.ID));
noteInfo.title = cursor.getString(cursor.getColumnIndexOrThrow(NoteColumns.SNIPPET));
// Read TITLE and SNIPPET
String dbTitle = "";
int titleIndex = cursor.getColumnIndex(NoteColumns.TITLE);
if (titleIndex != -1) {
dbTitle = cursor.getString(titleIndex);
}
noteInfo.snippet = cursor.getString(cursor.getColumnIndexOrThrow(NoteColumns.SNIPPET));
// Prioritize TITLE, fallback to SNIPPET
if (dbTitle != null && !dbTitle.trim().isEmpty()) {
noteInfo.title = dbTitle;
} else {
noteInfo.title = noteInfo.snippet;
}
noteInfo.parentId = cursor.getLong(cursor.getColumnIndexOrThrow(NoteColumns.PARENT_ID));
noteInfo.createdDate = cursor.getLong(cursor.getColumnIndexOrThrow(NoteColumns.CREATED_DATE));
noteInfo.modifiedDate = cursor.getLong(cursor.getColumnIndexOrThrow(NoteColumns.MODIFIED_DATE));

@ -52,6 +52,9 @@ public class WorkingNote {
/** 笔记模式 */
private int mMode;
/** 笔记标题 */
private String mTitle;
/** 提醒日期 */
private long mAlertDate;
@ -100,7 +103,8 @@ public class WorkingNote {
NoteColumns.BG_COLOR_ID,
NoteColumns.WIDGET_ID,
NoteColumns.WIDGET_TYPE,
NoteColumns.MODIFIED_DATE
NoteColumns.MODIFIED_DATE,
NoteColumns.TITLE
};
/** 数据 ID 列索引 */
@ -147,6 +151,8 @@ public class WorkingNote {
mContext = context;
mAlertDate = 0;
mModifiedDate = System.currentTimeMillis();
mTitle = "";
mContent = "";
mFolderId = folderId;
mNote = new Note();
mNoteId = 0;
@ -194,6 +200,14 @@ public class WorkingNote {
mWidgetType = cursor.getInt(NOTE_WIDGET_TYPE_COLUMN);
mAlertDate = cursor.getLong(NOTE_ALERTED_DATE_COLUMN);
mModifiedDate = cursor.getLong(NOTE_MODIFIED_DATE_COLUMN);
// Load title
int titleIndex = cursor.getColumnIndex(NoteColumns.TITLE);
if (titleIndex != -1) {
mTitle = cursor.getString(titleIndex);
} else {
mTitle = "";
}
}
cursor.close();
} else {
@ -295,6 +309,11 @@ public class WorkingNote {
}
}
mNote.setNoteValue(NoteColumns.MODIFIED_DATE, String.valueOf(System.currentTimeMillis()));
if (mTitle != null) {
mNote.setNoteValue(NoteColumns.TITLE, mTitle);
}
// 同步笔记数据
mNote.syncNote(mContext, mNoteId);
@ -356,6 +375,14 @@ public class WorkingNote {
* @param date
* @param set
*/
public void setTitle(String title) {
mTitle = title;
}
public String getTitle() {
return mTitle;
}
public void setAlertDate(long date, boolean set) {
if (date != mAlertDate) {
mAlertDate = date;

@ -95,6 +95,8 @@ public class NoteEditActivity extends AppCompatActivity implements OnClickListen
public ImageView ibSetBgColor;
public TextView tvCharCount;
public EditText etTitle;
}
private static final Map<Integer, Integer> sBgSelectorBtnsMap = new HashMap<Integer, Integer>();
@ -317,6 +319,7 @@ public class NoteEditActivity extends AppCompatActivity implements OnClickListen
mNoteHeaderHolder.ibSetBgColor = findViewById(R.id.btn_set_bg_color);
mNoteHeaderHolder.ibSetBgColor.setOnClickListener(this);
mNoteHeaderHolder.tvCharCount = findViewById(R.id.tv_char_count);
mNoteHeaderHolder.etTitle = findViewById(R.id.et_title);
mNoteEditor = findViewById(R.id.note_edit_view);
mNoteEditorPanel = findViewById(R.id.sv_note_edit);
@ -338,6 +341,26 @@ public class NoteEditActivity extends AppCompatActivity implements OnClickListen
public void afterTextChanged(Editable s) {
}
});
// Title TextWatcher
mNoteHeaderHolder.etTitle.addTextChangedListener(new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
// We can mark note as modified here if needed, or just let saveNote handle it
}
@Override
public void afterTextChanged(Editable s) {
// Update WorkingNote title
// mWorkingNote.setTitle(s.toString());
// Actually we should wait until saveNote to sync everything or sync immediately?
// The original logic syncs content only on save. Let's do the same for title.
}
});
// 设置背景颜色选择器的点击事件
for (int id : sBgSelectorBtnsMap.keySet()) {
@ -391,6 +414,7 @@ public class NoteEditActivity extends AppCompatActivity implements OnClickListen
mNoteEditor.setText(getHighlightQueryResult(mWorkingNote.getContent(), mUserQuery));
mNoteEditor.setSelection(mNoteEditor.getText().length());
}
mNoteHeaderHolder.etTitle.setText(mWorkingNote.getTitle());
for (Integer id : sBgSelectorSelectionMap.keySet()) {
findViewById(sBgSelectorSelectionMap.get(id)).setVisibility(View.GONE);
}
@ -1133,6 +1157,9 @@ public class NoteEditActivity extends AppCompatActivity implements OnClickListen
*/
private boolean saveNote() {
getWorkingText();
if (mNoteHeaderHolder != null && mNoteHeaderHolder.etTitle != null) {
mWorkingNote.setTitle(mNoteHeaderHolder.etTitle.getText().toString());
}
boolean saved = mWorkingNote.saveNote();
if (saved) {
/**

@ -252,7 +252,7 @@ public class NoteInfoAdapter extends BaseAdapter {
NotesRepository.NoteInfo note = (NotesRepository.NoteInfo) getItem(position);
if (note != null) {
String title = note.snippet;
String title = note.title;
if (title == null || title.trim().isEmpty()) {
title = "无标题";
}

@ -60,6 +60,7 @@ public class NoteItemData {
NoteColumns.WIDGET_ID,
NoteColumns.WIDGET_TYPE,
NoteColumns.TOP, // 新增TOP字段
NoteColumns.TITLE // 新增TITLE字段
};
// 列索引常量,用于从查询结果中获取对应列的数据
@ -76,6 +77,7 @@ public class NoteItemData {
private static final int WIDGET_ID_COLUMN = 10;
private static final int WIDGET_TYPE_COLUMN = 11;
private static final int TOP_COLUMN = 12;
private static final int TITLE_COLUMN = 13;
// 笔记ID
private long mId;
@ -95,6 +97,8 @@ public class NoteItemData {
private long mParentId;
// 笔记摘要
private String mSnippet;
// 笔记标题
private String mTitle;
// 笔记类型
private int mType;
// 桌面小部件ID
@ -150,6 +154,13 @@ public class NoteItemData {
} else {
mIsPinned = false;
}
// 读取标题
if (cursor.getColumnCount() > TITLE_COLUMN) {
mTitle = cursor.getString(TITLE_COLUMN);
} else {
mTitle = "";
}
mPhoneNumber = "";
// 如果是通话记录笔记,获取电话号码和联系人名称
@ -378,6 +389,15 @@ public class NoteItemData {
return mSnippet;
}
/**
*
*
* @return
*/
public String getTitle() {
return mTitle;
}
/**
*
*

@ -104,7 +104,14 @@ public class NotesListItem extends LinearLayout {
data.getNotesCount()));
mAlert.setVisibility(View.GONE);
} else {
mTitle.setText(DataUtils.getFormattedSnippet(data.getSnippet()));
// 优先显示标题,如果标题为空则显示摘要
String title = data.getTitle();
if (!android.text.TextUtils.isEmpty(title)) {
mTitle.setText(title);
} else {
mTitle.setText(DataUtils.getFormattedSnippet(data.getSnippet()));
}
if (data.hasAlert()) {
mAlert.setImageResource(R.drawable.clock);
mAlert.setVisibility(View.VISIBLE);

@ -85,6 +85,23 @@
android:background="@drawable/bg_btn_set_color" />
</LinearLayout>
<!-- Title Input Field -->
<EditText
android:id="@+id/et_title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@null"
android:hint="Title"
android:paddingLeft="15dip"
android:paddingRight="15dip"
android:paddingTop="10dip"
android:paddingBottom="5dip"
android:singleLine="true"
android:textSize="18sp"
android:textStyle="bold"
android:textColor="@android:color/black"
android:textColorHint="@android:color/darker_gray" />
<LinearLayout
android:id="@+id/sv_note_edit"
android:layout_width="match_parent"

Loading…
Cancel
Save