Compare commits

..

18 Commits

@ -0,0 +1,188 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="net.micode.notes"
android:versionCode="1"
android:versionName="0.1">
<uses-sdk android:minSdkVersion="16" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="com.android.launcher.permission.INSTALL_SHORTCUT" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.READ_CONTACTS" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.MANAGE_ACCOUNTS" />
<uses-permission android:name="android.permission.AUTHENTICATE_ACCOUNTS" />
<uses-permission android:name="android.permission.GET_ACCOUNTS" />
<uses-permission android:name="android.permission.USE_CREDENTIALS" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<application
android:icon="@drawable/my_icon_app"
android:label="@string/app_name"
android:requestLegacyExternalStorage="true"
tools:ignore="ExtraText">
<activity
android:name=".ui.RecordActivity"
android:label="Notes"
android:launchMode="standard" />
<activity
android:name=".ui.LoginActivity"
android:configChanges="keyboardHidden|orientation|screenSize"
android:label="@string/app_name"
android:launchMode="singleTop"
android:theme="@style/NoteTheme"
android:windowSoftInputMode="adjustPan">
<!-- android:uiOptions="splitActionBarWhenNarrow" -->
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name=".ui.SplashActivity"
android:configChanges="orientation|keyboardHidden|screenSize"
android:exported="true"
android:label="@string/title_activity_splash"
android:theme="@style/Theme.Space2.Fullscreen">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name=".ui.ChangedLoginPassword"
android:configChanges="keyboardHidden|orientation|screenSize"
android:label="@string/app_name"
android:launchMode="singleTop"
android:theme="@style/NoteTheme"
android:windowSoftInputMode="adjustPan"></activity>
<activity
android:name=".ui.RegisterLoginPassword"
android:configChanges="keyboardHidden|orientation|screenSize"
android:label="@string/app_name"
android:launchMode="singleTop"
android:theme="@style/NoteTheme"
android:windowSoftInputMode="adjustPan"></activity>
<activity
android:name=".ui.DeleteLoginPassword"
android:configChanges="keyboardHidden|orientation|screenSize"
android:label="@string/app_name"
android:launchMode="singleTop"
android:theme="@style/NoteTheme"
android:windowSoftInputMode="adjustPan"></activity>
<activity
android:name=".ui.NotesListActivity"
android:configChanges="keyboardHidden|orientation|screenSize"
android:label="@string/app_name"
android:launchMode="standard"
android:theme="@style/NoteTheme"
android:windowSoftInputMode="adjustPan">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<action android:name="android.intent.action.SEARCH" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<meta-data
android:name="android.app.searchable"
android:resource="@xml/searchable"/>
</activity>
<activity
android:name=".ui.NoteEditActivity"
android:configChanges="keyboardHidden|orientation|screenSize"
android:launchMode="singleTop"
android:theme="@style/NoteTheme">
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="vnd.android.cursor.item/text_note" />
<data android:mimeType="vnd.android.cursor.item/call_note" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.INSERT_OR_EDIT" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="vnd.android.cursor.item/text_note" />
<data android:mimeType="vnd.android.cursor.item/call_note" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.SEARCH" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
<meta-data
android:name="android.app.searchable"
android:resource="@xml/searchable" />
</activity>
<provider
android:name=".data.NotesProvider"
android:authorities="micode_notes"
android:multiprocess="true" />
<receiver
android:name=".widget.NoteWidgetProvider_2x"
android:label="@string/app_widget2x2">
<intent-filter>
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
<action android:name="android.appwidget.action.APPWIDGET_DELETED" />
<action android:name="android.intent.action.PRIVACY_MODE_CHANGED" />
</intent-filter>
<meta-data
android:name="android.appwidget.provider"
android:resource="@xml/widget_2x_info" />
</receiver>
<receiver
android:name=".widget.NoteWidgetProvider_4x"
android:label="@string/app_widget4x4">
<intent-filter>
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
<action android:name="android.appwidget.action.APPWIDGET_DELETED" />
<action android:name="android.intent.action.PRIVACY_MODE_CHANGED" />
</intent-filter>
<meta-data
android:name="android.appwidget.provider"
android:resource="@xml/widget_4x_info" />
</receiver>
<receiver android:name=".ui.AlarmInitReceiver">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
<receiver
android:name=".ui.AlarmReceiver"
android:process=":remote"></receiver>
<activity
android:name=".ui.AlarmAlertActivity"
android:label="@string/app_name"
android:launchMode="singleInstance"
android:theme="@android:style/Theme.Holo.Wallpaper.NoTitleBar"></activity>
<activity
android:name=".ui.NotesPreferenceActivity"
android:label="@string/preferences_title"
android:launchMode="singleTop"
android:theme="@android:style/Theme.Holo.Light"></activity>
<service
android:name=".gtask.remote.GTaskSyncService"
android:exported="false"></service>
</application>
</manifest>

@ -18,6 +18,7 @@ package net.micode.notes.data;
import android.net.Uri;
public class Notes {
public static final String AUTHORITY = "micode_notes";
public static final String TAG = "Notes";
public static final int TYPE_NOTE = 0;
@ -62,6 +63,10 @@ public class Notes {
public static final Uri CONTENT_DATA_URI = Uri.parse("content://" + AUTHORITY + "/data");
public interface NoteColumns {
//置顶
// public static final String TOP = "top";
/**
* The unique ID for a row
* <P> Type: INTEGER (long) </P>
@ -165,6 +170,7 @@ public class Notes {
* <P> Type : INTEGER (long) </P>
*/
public static final String VERSION = "version";
}
public interface DataColumns {
@ -276,4 +282,6 @@ public class Notes {
public static final Uri CONTENT_URI = Uri.parse("content://" + AUTHORITY + "/call_note");
}
}

@ -61,6 +61,7 @@ public class NotesDatabaseHelper extends SQLiteOpenHelper {
NoteColumns.ORIGIN_PARENT_ID + " INTEGER NOT NULL DEFAULT 0," +
NoteColumns.GTASK_ID + " TEXT NOT NULL DEFAULT ''," +
NoteColumns.VERSION + " INTEGER NOT NULL DEFAULT 0" +
// NoteColumns.TOP + " INTEGER NOT NULL DEFAULT 0" +
")";
private static final String CREATE_DATA_TABLE_SQL =
@ -322,6 +323,16 @@ public class NotesDatabaseHelper extends SQLiteOpenHelper {
oldVersion++;
}
/*
if (oldVersion == 4) {
upgradeToV5(db);
oldVersion++;
}
*/
if (reCreateTriggers) {
reCreateNoteTableTriggers(db);
reCreateDataTableTriggers(db);
@ -359,4 +370,12 @@ public class NotesDatabaseHelper extends SQLiteOpenHelper {
db.execSQL("ALTER TABLE " + TABLE.NOTE + " ADD COLUMN " + NoteColumns.VERSION
+ " INTEGER NOT NULL DEFAULT 0");
}
/*
private void upgradeToV5(SQLiteDatabase db){
db.execSQL("ALTER TABLE " + TABLE.NOTE + " ADD COLUMN" + NoteColumns.TOP
+ " INTEGER NOT NULL DEFAULT 0");
}
*/
}

@ -33,12 +33,13 @@ import net.micode.notes.R;
import net.micode.notes.data.Notes.DataColumns;
import net.micode.notes.data.Notes.NoteColumns;
import net.micode.notes.data.NotesDatabaseHelper.TABLE;
import net.micode.notes.gtask.data.SqlNote;
public class NotesProvider extends ContentProvider {
private static final UriMatcher mMatcher;
private NotesDatabaseHelper mHelper;
private static NotesDatabaseHelper mHelper;
private static final String TAG = "NotesProvider";
@ -302,4 +303,6 @@ public class NotesProvider extends ContentProvider {
return null;
}
}

@ -45,6 +45,7 @@ public class SqlData {
DataColumns.DATA3
};
public static final int DATA_ID_COLUMN = 0;
public static final int DATA_MIME_TYPE_COLUMN = 1;

@ -43,13 +43,14 @@ public class SqlNote {
private static final int INVALID_ID = -99999;
public static final String[] PROJECTION_NOTE = new String[] {
NoteColumns.ID, NoteColumns.ALERTED_DATE, NoteColumns.BG_COLOR_ID,
NoteColumns.CREATED_DATE, NoteColumns.HAS_ATTACHMENT, NoteColumns.MODIFIED_DATE,
NoteColumns.NOTES_COUNT, NoteColumns.PARENT_ID, NoteColumns.SNIPPET, NoteColumns.TYPE,
NoteColumns.WIDGET_ID, NoteColumns.WIDGET_TYPE, NoteColumns.SYNC_ID,
NoteColumns.LOCAL_MODIFIED, NoteColumns.ORIGIN_PARENT_ID, NoteColumns.GTASK_ID,
NoteColumns.VERSION
NoteColumns.VERSION,//NoteColumns.TOP
};
public static final int ID_COLUMN = 0;
@ -86,6 +87,8 @@ public class SqlNote {
public static final int VERSION_COLUMN = 16;
// public static final int Top_COLUMN = 17;
private Context mContext;
private ContentResolver mContentResolver;
@ -118,6 +121,8 @@ public class SqlNote {
private long mVersion;
private String mTop;
private ContentValues mDiffNoteValues;
private ArrayList<SqlData> mDataList;
@ -141,6 +146,8 @@ public class SqlNote {
mVersion = 0;
mDiffNoteValues = new ContentValues();
mDataList = new ArrayList<SqlData>();
//mTop = getmTop();
}
public SqlNote(Context context, Cursor c) {
@ -152,6 +159,8 @@ public class SqlNote {
if (mType == Notes.TYPE_NOTE)
loadDataContent();
mDiffNoteValues = new ContentValues();
// mTop = getmTop();
}
public SqlNote(Context context, long id) {
@ -164,8 +173,16 @@ public class SqlNote {
loadDataContent();
mDiffNoteValues = new ContentValues();
//mTop = getmTop();
}
/*
public String getmTop(){
return mTop;
}
*/
private void loadFromCursor(long id) {
Cursor c = null;
try {
@ -198,6 +215,8 @@ public class SqlNote {
mWidgetId = c.getInt(WIDGET_ID_COLUMN);
mWidgetType = c.getInt(WIDGET_TYPE_COLUMN);
mVersion = c.getLong(VERSION_COLUMN);
//mTop = c.getString(Top_COLUMN);
}
private void loadDataContent() {

@ -250,4 +250,14 @@ public class Note {
return null;
}
}
/*
public void setTopValue(String key, String value) {
mNoteDiffValues.put(key, value);
}
*/
}

@ -29,6 +29,7 @@ import net.micode.notes.data.Notes.DataColumns;
import net.micode.notes.data.Notes.DataConstants;
import net.micode.notes.data.Notes.NoteColumns;
import net.micode.notes.data.Notes.TextNote;
import net.micode.notes.data.NotesProvider;
import net.micode.notes.tool.ResourceParser.NoteBgResources;
@ -38,7 +39,7 @@ public class WorkingNote {
// Note Id
private long mNoteId;
// Note content
private String mContent;
public String mContent;
// Note mode
private int mMode;
@ -60,6 +61,10 @@ public class WorkingNote {
private boolean mIsDeleted;
///
// private String mTop = "0";
//
private NoteSettingChangedListener mNoteSettingStatusListener;
public static final String[] DATA_PROJECTION = new String[] {
@ -101,6 +106,8 @@ public class WorkingNote {
private static final int NOTE_MODIFIED_DATE_COLUMN = 5;
//private static final int NOTE_TOP_COLUMN = 6;
// New note construct
private WorkingNote(Context context, long folderId) {
mContext = context;
@ -112,6 +119,8 @@ public class WorkingNote {
mIsDeleted = false;
mMode = 0;
mWidgetType = Notes.TYPE_WIDGET_INVALIDE;
// mTop = String.valueOf(getTopId());
}
// Existing note construct
@ -137,6 +146,8 @@ public class WorkingNote {
mWidgetType = cursor.getInt(NOTE_WIDGET_TYPE_COLUMN);
mAlertDate = cursor.getLong(NOTE_ALERTED_DATE_COLUMN);
mModifiedDate = cursor.getLong(NOTE_MODIFIED_DATE_COLUMN);
// mTop = cursor.getString(NOTE_TOP_COLUMN);
}
cursor.close();
} else {
@ -365,4 +376,21 @@ public class WorkingNote {
*/
void onCheckListModeChanged(int oldMode, int newMode);
}
/*
public int getTopId() {
if (mTop.equals("1")) {
return 1;
}
return 0;
}
public void setTop(String Top){
if (mTop!=Top) {
mTop = Top;
mNote.setTopValue(NoteColumns.TOP,mTop);
}
}
*/
}

@ -0,0 +1,69 @@
package net.micode.notes.ui;
import android.app.Activity;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.view.WindowManager;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;
import net.micode.notes.R;
public class ChangedLoginPassword extends Activity{
EditText OldPassword;
EditText NewPassword;
EditText AckPassword;
Button Acknowledged;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_change_loginpassword);
getWindow().setSoftInputMode(
WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE
| WindowManager.LayoutParams.SOFT_INPUT_STATE_VISIBLE);
OldPassword=(EditText) findViewById(R.id.old_password);
NewPassword=(EditText) findViewById(R.id.new_password);
AckPassword=(EditText) findViewById(R.id.ack_password);
Acknowledged=(Button)findViewById(R.id.Bt_Acknowledged);
Acknowledged.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
String old_password = OldPassword.getText().toString();
String new_password = NewPassword.getText().toString();
String ack_password = AckPassword.getText().toString();
SharedPreferences pref=getSharedPreferences("user management",MODE_PRIVATE);
String login_password=pref.getString("password","");
if(old_password.equals("")==true || new_password.equals("")==true || ack_password.equals("")==true) {
Toast.makeText(ChangedLoginPassword.this, "密码不能为空", Toast.LENGTH_SHORT).show();
}else if (new_password.equals(ack_password) == false) {
Toast.makeText(ChangedLoginPassword.this, "新建密码与重复密码不匹配,请重新输入密码", Toast.LENGTH_SHORT).show();
AckPassword.setText("");
}else if(old_password.equals(login_password) == false){
Toast.makeText(ChangedLoginPassword.this, "原有密码错误,请重新输入密码", Toast.LENGTH_SHORT).show();
OldPassword.setText("");
}
else if (new_password.equals(ack_password) == true && old_password.equals(login_password) == true){
SharedPreferences.Editor editor=getSharedPreferences("user management", MODE_PRIVATE).edit();
editor.putString("password",new_password);
editor.apply();
Toast.makeText(ChangedLoginPassword.this, "修改密码成功", Toast.LENGTH_SHORT).show();
Intent intent=new Intent(ChangedLoginPassword.this,NotesListActivity.class);
startActivity(intent);
finish();
}
}
});
}
@Override
public void onBackPressed() {
Intent intent=new Intent(ChangedLoginPassword.this,NotesListActivity.class);
startActivity(intent);
finish();
}
}

@ -0,0 +1,63 @@
package net.micode.notes.ui;
import android.app.Activity;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.view.WindowManager;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;
import net.micode.notes.R;
public class DeleteLoginPassword extends Activity{
EditText password01;
Button Acknowledged;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_delete_loginpassword);
getWindow().setSoftInputMode(
WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE
| WindowManager.LayoutParams.SOFT_INPUT_STATE_VISIBLE);
password01=(EditText) findViewById(R.id.old_password);
Acknowledged=(Button)findViewById(R.id.Bt_Acknowledged);
Acknowledged.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
String text02 = password01.getText().toString();
if(text02.equals("")==true)
Toast.makeText(DeleteLoginPassword.this, "密码不能为空", Toast.LENGTH_SHORT).show();
SharedPreferences pref=getSharedPreferences("user management",MODE_PRIVATE);
String password = pref.getString("password","");
if(password.equals("")==false&&password.equals(text02)==true){
SharedPreferences.Editor editor=getSharedPreferences("user management",
MODE_PRIVATE).edit();
editor.putBoolean("user",false);//false表示已经设置登录密码
editor.putString("password","");
editor.apply();
Toast.makeText(DeleteLoginPassword.this, "已经删除登录密码", Toast.LENGTH_SHORT).show();
Intent intent=new Intent(DeleteLoginPassword.this,NotesListActivity.class);
startActivity(intent);
finish();
}
else{
Toast.makeText(DeleteLoginPassword.this, "密码错误", Toast.LENGTH_SHORT).show();
password01.setText("");//把密码框内输入过的错误密码清空
}
}
});
}
@Override
public void onBackPressed() {
Intent intent=new Intent(DeleteLoginPassword.this,NotesListActivity.class);
startActivity(intent);
finish();
}
}

@ -0,0 +1,58 @@
package net.micode.notes.ui;
import android.app.Activity;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.view.WindowManager;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;
import net.micode.notes.R;
public class LoginActivity extends Activity {
EditText lg_password;
Button lg_login;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
SharedPreferences pref=getSharedPreferences("user management",MODE_PRIVATE);
boolean User_boolean = pref.getBoolean("user",false);//获取用户是否设置了密码
if(!User_boolean) //User_boolean = false时没有设置密码直接跳转到便签主界面
{
Intent intent=new Intent(LoginActivity.this,SplashActivity.class);
startActivity(intent);
finish();
}
setContentView(R.layout.activity_login);
getWindow().setSoftInputMode(
WindowManager.LayoutParams.SOFT_INPUT_STATE_VISIBLE
| WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE);
lg_password=(EditText) findViewById(R.id.lg_password);
lg_login=(Button)findViewById(R.id.login);
lg_login.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
SharedPreferences pref=getSharedPreferences("user management",MODE_PRIVATE);
String password=pref.getString("password","");
if(password.equals("")==false&&password.equals(lg_password.getText().toString())==true){
Intent intent=new Intent(LoginActivity.this,SplashActivity.class);
startActivity(intent);
finish();
}
else{
Toast.makeText(LoginActivity.this, "密码错误", Toast.LENGTH_SHORT).show();
lg_password.setText("");//把密码框内输入过的错误密码清空
}
}
}
);
}
}

@ -16,25 +16,40 @@
package net.micode.notes.ui;
import android.Manifest;
import android.app.Activity;
import android.app.AlarmManager;
import android.app.AlertDialog;
import android.app.PendingIntent;
import android.app.SearchManager;
import android.appwidget.AppWidgetManager;
import android.content.ContentResolver;
import android.content.ContentUris;
import android.content.ContentValues;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.pm.PackageManager;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Paint;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.preference.PreferenceManager;
import android.provider.DocumentsContract;
import android.provider.MediaStore;
import android.text.Editable;
import android.text.Spannable;
import android.text.SpannableString;
import android.text.Spanned;
import android.text.TextUtils;
import android.text.TextWatcher;
import android.text.format.DateUtils;
import android.text.style.BackgroundColorSpan;
import android.text.style.ImageSpan;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.Menu;
@ -43,10 +58,12 @@ import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.WindowManager;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.CompoundButton;
import android.widget.CompoundButton.OnCheckedChangeListener;
import android.widget.EditText;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
@ -65,6 +82,11 @@ import net.micode.notes.ui.NoteEditText.OnTextViewChangeListener;
import net.micode.notes.widget.NoteWidgetProvider_2x;
import net.micode.notes.widget.NoteWidgetProvider_4x;
import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
@ -96,7 +118,9 @@ public class NoteEditActivity extends Activity implements OnClickListener,
public ImageView ibSetBgColor;
}
private static final Map<Integer, Integer> sBgSelectorBtnsMap = new HashMap<Integer, Integer>();
static {
//put实现了将指定的颜色的值和对应的按键相连接
sBgSelectorBtnsMap.put(R.id.iv_bg_yellow, ResourceParser.YELLOW);
@ -107,6 +131,7 @@ public class NoteEditActivity extends Activity implements OnClickListener,
}
private static final Map<Integer, Integer> sBgSelectorSelectionMap = new HashMap<Integer, Integer>();
static {
sBgSelectorSelectionMap.put(ResourceParser.YELLOW, R.id.iv_bg_yellow_select);
sBgSelectorSelectionMap.put(ResourceParser.RED, R.id.iv_bg_red_select);
@ -116,6 +141,7 @@ public class NoteEditActivity extends Activity implements OnClickListener,
}
private static final Map<Integer, Integer> sFontSizeBtnsMap = new HashMap<Integer, Integer>();
static {
sFontSizeBtnsMap.put(R.id.ll_font_large, ResourceParser.TEXT_LARGE);
sFontSizeBtnsMap.put(R.id.ll_font_small, ResourceParser.TEXT_SMALL);
@ -124,6 +150,7 @@ public class NoteEditActivity extends Activity implements OnClickListener,
}
private static final Map<Integer, Integer> sFontSelectorSelectionMap = new HashMap<Integer, Integer>();
static {
sFontSelectorSelectionMap.put(ResourceParser.TEXT_LARGE, R.id.iv_large_select);
sFontSelectorSelectionMap.put(ResourceParser.TEXT_SMALL, R.id.iv_small_select);
@ -131,6 +158,13 @@ public class NoteEditActivity extends Activity implements OnClickListener,
sFontSelectorSelectionMap.put(ResourceParser.TEXT_SUPER, R.id.iv_super_select);
}
//功能增加:统计字符数
private EditText editText;
private TextView textView;
//
private static final String TAG = "NoteEditActivity";
private HeadViewHolder mNoteHeaderHolder;
@ -171,6 +205,15 @@ public class NoteEditActivity extends Activity implements OnClickListener,
private String mUserQuery;
private Pattern mPattern;
private final int PHOTO_REQUEST = 1;//请求码
public static int topId;//是否置顶1表示置顶0表示没置顶
private int REQUEST_CODE_RECORD = 2;//录音功能
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
@ -181,6 +224,95 @@ public class NoteEditActivity extends Activity implements OnClickListener,
return;
}
initResources();
//绑定
editText = (EditText) findViewById(R.id.note_edit_view);
textView = (TextView) findViewById(R.id.text_num);
count();//统计字符数
//添加功能:在便签中加入图片
//根据id获取添加图片按钮
final ImageButton add_img_btn = (ImageButton) findViewById(R.id.add_img_btn);
//为点击图片按钮设置监听器
add_img_btn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Log.d(TAG, "onClick: click add image button");
//ACTION_GET_CONTENT: 允许用户选择特殊种类的数据,并返回(特殊种类的数据:一张相片)
Intent loadImage = new Intent(Intent.ACTION_GET_CONTENT);
//Category属性用于指定当前动作Action被执行的环境.
//CATEGORY_OPENABLE; 用来指示一个ACTION_GET_CONTENT的intent
loadImage.addCategory(Intent.CATEGORY_OPENABLE);
loadImage.setType("image/*");
startActivityForResult(loadImage, PHOTO_REQUEST);
}
});
}
/**
* @description
* @param 1:oriText
* @param 2:
* @param 3:
* @return :String
* @author zhangchaoqun
*/
private String Textchange(String oriText){
StringBuffer stringBuffer = new StringBuffer(oriText);
int Flag1 = -1;
int Flag2 = -1;
do {//不计入表示图片的字符
Flag1 = stringBuffer.indexOf("<img");
Flag2 = stringBuffer.indexOf(">");
if (Flag1 != -1 && Flag2 != -1) {
stringBuffer = stringBuffer.replace(Flag1, Flag2+1, "");
}
} while (Flag1 != -1 && Flag2 != -1);
do {//不计入换行字符
Flag1 = stringBuffer.indexOf("\n");
if (Flag1 != -1){
stringBuffer = stringBuffer.replace(Flag1, Flag1+1, "");
}
} while (Flag1 != -1);
do {//不计入空格字符
Flag1 = stringBuffer.indexOf(" ");
if (Flag1 != -1) {
stringBuffer = stringBuffer.replace(Flag1, Flag1+1, "");
}
} while (Flag1 != -1);
return stringBuffer.toString();
}
/**
* @description :textView
* @param 1:
* @param 2:
* @param 3:
* @return :
* @author zhangchaoqun
*/
private void count() {
editText.addTextChangedListener(new TextWatcher() {
int currentLength = 0;
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
textView.setText("字符数:" + currentLength);
}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
currentLength = Textchange(String.valueOf(editText.getText())).length();
}
@Override
public void afterTextChanged(Editable s) {
textView.setText("字符数:" + currentLength);
}
});
}
/**
@ -189,11 +321,11 @@ public class NoteEditActivity extends Activity implements OnClickListener,
*/
/**
* @description :
* @param 1:savedInstanceState
* @param 2:
* @param 3:
* @return :void
* @description :
* @author zhangchaoqun
*/
@Override
@ -213,11 +345,11 @@ public class NoteEditActivity extends Activity implements OnClickListener,
/**
* @description :IntentinitActivityState
* @param 1:intent
* @param 2:
* @param 3:
* @return :bool
* @description :IntentinitActivityState
* @author zhangchaoqun
*/
private boolean initActivityState(Intent intent) {
@ -323,15 +455,16 @@ public class NoteEditActivity extends Activity implements OnClickListener,
protected void onResume() {
super.onResume();
initNoteScreen();
initEditText();//初始化便签模板
}
/**
* @description :
* @param 1:
* @param 2:
* @param 3:
* @return :void
* @description :
* @author zhangchaoqun
*/
private void initNoteScreen() {
@ -360,15 +493,59 @@ public class NoteEditActivity extends Activity implements OnClickListener,
* is not ready
*/
showAlertHeader();
//把路径转换成image图片
convertToImage();
}
//路径字符串格式 转换为 图片image格式
private void convertToImage() {
NoteEditText noteEditText = (NoteEditText) findViewById(R.id.note_edit_view); //获取当前的edit
Editable editable = noteEditText.getText();//获取text
String noteText = editable.toString(); //将note内容转换为字符串
int length = editable.length(); //内容的长度
/*img [local]+uri+[/local]uri
[local]7
[local][/local]15path
[local]lenpath
*/
for(int i = 0; i < length; i++) {
for(int j = i; j < length; j++) {
String img_fragment = noteText.substring(i, j+1); //img_fragment关于图片路径的片段
if(img_fragment.length() > 15 && img_fragment.endsWith("[/local]") && img_fragment.startsWith("[local]")){
int limit = 7;
int len = img_fragment.length()-15;
String path = img_fragment.substring(limit,limit+len);//获取到了图片路径
Bitmap bitmap = null;
Log.d(TAG, "图片的路径是:"+path);
try {
bitmap = BitmapFactory.decodeFile(path);//将图片路径解码为图片格式
} catch (Exception e) {
e.printStackTrace();
}
if(bitmap!=null){ //若图片存在
Log.d(TAG, "图片不为null");
ImageSpan imageSpan = new ImageSpan(NoteEditActivity.this, bitmap);
//创建一个SpannableString对象以便插入用ImageSpan对象封装的图像
String ss = "[local]" + path + "[/local]";
SpannableString spannableString = new SpannableString(ss);
//将指定的标记对象附加到文本的开始...结束范围
spannableString.setSpan(imageSpan, 0, ss.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
Log.d(TAG, "Create spannable string success!");
Editable edit_text = noteEditText.getEditableText();
edit_text.delete(i,i+len+15); //删掉图片路径的文字
edit_text.insert(i, spannableString); //在路径的起始位置插入图片
}
}
}
}
}
/**
* @description :
* @param 1:
* @param 2:
* @param 3:
* @return :void
* @description :
* @author zhangchaoqun
*/
private void showAlertHeader() {
@ -392,7 +569,8 @@ public class NoteEditActivity extends Activity implements OnClickListener,
else {
mNoteHeaderHolder.tvAlertDate.setVisibility(View.GONE);
mNoteHeaderHolder.ivAlertIcon.setVisibility(View.GONE);
};
}
;
}
@Override
@ -441,11 +619,11 @@ public class NoteEditActivity extends Activity implements OnClickListener,
/**
* @description :
* @param 1:view
* @param 2:ev
* @param 3:
* @return :bool
* @description :
* @author zhangchaoqun
*/
private boolean inRangeOfView(View view, MotionEvent ev) {
@ -485,7 +663,8 @@ public class NoteEditActivity extends Activity implements OnClickListener,
for (int id : sFontSizeBtnsMap.keySet()) {
View view = findViewById(id);
view.setOnClickListener(this);
};
}
;
mSharedPrefs = PreferenceManager.getDefaultSharedPreferences(this);
mFontSizeId = mSharedPrefs.getInt(PREFERENCE_FONT_SIZE, ResourceParser.BG_DEFAULT_FONT_SIZE);
/**
@ -497,6 +676,7 @@ public class NoteEditActivity extends Activity implements OnClickListener,
mFontSizeId = ResourceParser.BG_DEFAULT_FONT_SIZE;
}
mEditTextList = (LinearLayout) findViewById(R.id.note_edit_list);
}
@Override
@ -510,11 +690,11 @@ public class NoteEditActivity extends Activity implements OnClickListener,
/**
* @description :Widget
* @param 1:
* @param 2:
* @param 3:
* @return :void
* @description :Widget
* @author zhangchaoqun
*/
private void updateWidget() {
@ -538,11 +718,11 @@ public class NoteEditActivity extends Activity implements OnClickListener,
/**
* @description :
* @param 1:
* @param 2:
* @param 3:
* @return :void
* @description :
* @author zhangchaoqun
*/
public void onClick(View v) {
@ -602,11 +782,11 @@ public class NoteEditActivity extends Activity implements OnClickListener,
/**
* @description :
* @param 1:menu
* @param 2:
* @param 3:
* @return :bool
* @description :
* @author zhangchaoqun
*/
@Override
@ -632,20 +812,31 @@ public class NoteEditActivity extends Activity implements OnClickListener,
} else {
menu.findItem(R.id.menu_delete_remind).setVisible(false);
}
/*
topId=mWorkingNote.getTopId();
if (topId == 1 ) {
menu.findItem(R.id.menu_top).setTitle("取消置顶");
} else if(topId == 0){
menu.findItem(R.id.menu_top).setTitle("置顶");
}
*/
return true;
}
/**
* @description :
* @param 1:item
* @param 2:
* @param 3:
* @return :bool
* @description :
* @author zhangchaoqun
*/
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// final Button topBtn = (Button) findViewById(R.id.menu_top);
//根据菜单的id来编辑相关项目
int itemId = item.getItemId();
//创建一个新的便签
@ -706,16 +897,31 @@ public class NoteEditActivity extends Activity implements OnClickListener,
else if (itemId == R.id.menu_delete_remind) {
mWorkingNote.setAlertDate(0, false);
}
//录音
else if(itemId==R.id.menu_insert_record){
insertRecord();
}
/*
else if(itemId==R.id.menu_top) {
if ((mWorkingNote.getTopId()) == 1) {
topId = 0;
} else if ((mWorkingNote.getTopId()) == 0){
topId = 1;
}
mWorkingNote.setTop((mWorkingNote.getTopId()) == 1 ? "0" : "1");
}
*/
return true;
}
/**
* @description :
* @param 1:
* @param 2:
* @param 3:
* @return :void
* @description :
* @author zhangchaoqun
*/
private void setReminder() {
@ -738,11 +944,11 @@ public class NoteEditActivity extends Activity implements OnClickListener,
*/
/**
* @description :便
* @param 1:context
* @param 2:info
* @param 3:
* @return :void
* @description :便
* @author zhangchaoqun
*/
private void sendTo(Context context, String info) {
@ -758,11 +964,11 @@ public class NoteEditActivity extends Activity implements OnClickListener,
/**
* @description :便
* @param 1:
* @param 2:
* @param 3:
* @return :void
* @description :便
* @author zhangchaoqun
*/
private void createNewNote() {
@ -784,11 +990,11 @@ public class NoteEditActivity extends Activity implements OnClickListener,
/**
* @description :便
* @param 1:
* @param 2:
* @param 3:
* @return :void
* @description :便
* @author zhangchaoqun
*/
private void deleteCurrentNote() {
@ -825,11 +1031,11 @@ public class NoteEditActivity extends Activity implements OnClickListener,
/**
* @description :NotesPreferenceActivity
* @param 1:
* @param 2:
* @param 3:
* @return :bool
* @description :NotesPreferenceActivity
* @author zhangchaoqun
*/
private boolean isSyncMode() {
@ -838,11 +1044,11 @@ public class NoteEditActivity extends Activity implements OnClickListener,
/**
* @description :
* @param 1:date
* @param 2:set
* @param 3:
* @return :void
* @description :
* @author zhangchaoqun
*/
public void onClockAlertChanged(long date, boolean set) {
@ -892,11 +1098,11 @@ public class NoteEditActivity extends Activity implements OnClickListener,
/**
* @description :
* @param 1:index
* @param 2:text
* @param 3:
* @return :void
* @description :
* @author zhangchaoqun
*/
public void onEditTextDelete(int index, String text) {
@ -931,11 +1137,11 @@ public class NoteEditActivity extends Activity implements OnClickListener,
/**
* @description :
* @param 1:index
* @param 2:text
* @param 3:
* @return :void
* @description :
* @author zhangchaoqun
*/
public void onEditTextEnter(int index, String text) {
@ -964,11 +1170,11 @@ public class NoteEditActivity extends Activity implements OnClickListener,
/**
* @description :
* @param 1:text
* @param 2:
* @param 3:
* @return :void
* @description :
* @author zhangchaoqun
*/
private void switchToListMode(String text) {
@ -993,11 +1199,11 @@ public class NoteEditActivity extends Activity implements OnClickListener,
/**
* @description :
* @param 1:fullText
* @param 2:userQuery
* @param 3:
* @return :Spannable
* @description :
* @author zhangchaoqun
*/
private Spannable getHighlightQueryResult(String fullText, String userQuery) {
@ -1022,11 +1228,11 @@ public class NoteEditActivity extends Activity implements OnClickListener,
/**
* @description :
* @param 1:item
* @param 2:index
* @param 3:
* @return :View
* @description :
* @author zhangchaoqun
*/
private View getListItem(String item, int index) {
@ -1069,11 +1275,11 @@ public class NoteEditActivity extends Activity implements OnClickListener,
/**
* @description :便
* @param 1:index
* @param 2:hasText
* @param 3:
* @return :void
* @description :便
* @author zhangchaoqun
*/
public void onTextChange(int index, boolean hasText) {
@ -1092,11 +1298,11 @@ public class NoteEditActivity extends Activity implements OnClickListener,
/**
* @description :
* @param 1:oldMode
* @param 2:newMode
* @param 3:
* @return :void
* @description :
* @author zhangchaoqun
*/
public void onCheckListModeChanged(int oldMode, int newMode) {
@ -1112,15 +1318,16 @@ public class NoteEditActivity extends Activity implements OnClickListener,
mEditTextList.setVisibility(View.GONE);
mNoteEditor.setVisibility(View.VISIBLE);
}
convertToImage(); //退出清单模式,应该将有图片的地方显示出来
}
/**
* @description :
* @param 1:
* @param 2:
* @param 3:
* @return :bool
* @description :
* @author zhangchaoqun
*/
private boolean getWorkingText() {
@ -1157,11 +1364,11 @@ public class NoteEditActivity extends Activity implements OnClickListener,
/**
* @description :便
* @param 1:
* @param 2:
* @param 3:
* @return :bool
* @description :便
* @author zhangchaoqun
*/
private boolean saveNote() {
@ -1184,11 +1391,11 @@ public class NoteEditActivity extends Activity implements OnClickListener,
/**
* @description :便
* @param 1:
* @param 2:
* @param 3:
* @return :void
* @description :便
* @author zhangchaoqun
*/
private void sendToDesktop() {
@ -1239,11 +1446,11 @@ public class NoteEditActivity extends Activity implements OnClickListener,
/**
* @description :
* @param 1:content
* @param 2:
* @param 3:
* @return :String
* @description :
* @author zhangchaoqun
*/
private String makeShortcutIconTitle(String content) {
@ -1256,11 +1463,11 @@ public class NoteEditActivity extends Activity implements OnClickListener,
/**
* @description :
* @param 1:resId
* @param 2:
* @param 3:
* @return :void
* @description :
* @author zhangchaoqun
*/
private void showToast(int resId) {
@ -1269,14 +1476,191 @@ public class NoteEditActivity extends Activity implements OnClickListener,
/**
* @description :duration
* @param 1:resId
* @param 2:duration
* @param 3:
* @return :void
* @description :duration
* @author zhangchaoqun
*/
private void showToast(int resId, int duration) {
Toast.makeText(this, resId, duration).show();
}
//添加功能:在便签中加入图片**********
//重写onActivityResult()来处理返回的数据
protected void onActivityResult(int requestCode, int resultCode, Intent intent) {
super.onActivityResult(requestCode, resultCode, intent);
ContentResolver resolver = getContentResolver();
switch (requestCode) {
case PHOTO_REQUEST:
Uri originalUri = intent.getData(); //1.获得图片的真实路径
Bitmap bitmap = null;
try {
bitmap = BitmapFactory.decodeStream(resolver.openInputStream(originalUri));//2.解码图片
} catch (FileNotFoundException e) {
Log.d(TAG, "onActivityResult: get file_exception");
e.printStackTrace();
}
if(bitmap != null){
//3.根据Bitmap对象创建ImageSpan对象
Log.d(TAG, "onActivityResult: bitmap is not null");
ImageSpan imageSpan = new ImageSpan(NoteEditActivity.this, bitmap);
String path = getPath(this,originalUri);
//4.使用[local][/local]将path括起来用于之后方便识别图片路径在note中的位置
String img_fragment= "[local]" + path + "[/local]";
//创建一个SpannableString对象以便插入用ImageSpan对象封装的图像
SpannableString spannableString = new SpannableString(img_fragment);
spannableString.setSpan(imageSpan, 0, img_fragment.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
//5.将选择的图片追加到EditText中光标所在位置
NoteEditText e = (NoteEditText) findViewById(R.id.note_edit_view);
int index = e.getSelectionStart(); //获取光标所在位置
Log.d(TAG, "Index是: " + index);
Editable edit_text = e.getEditableText();
edit_text.insert(index, spannableString); //将图片插入到光标所在位置
mWorkingNote.mContent = e.getText().toString();
//6.把改动提交到数据库中,两个数据库表都要改的
ContentResolver contentResolver = getContentResolver();
ContentValues contentValues = new ContentValues();
final long id = mWorkingNote.getNoteId();
contentValues.put("snippet",mWorkingNote.mContent);
contentResolver.update(Uri.parse("content://micode_notes/note"), contentValues,"_id=?",new String[]{""+id});
ContentValues contentValues1 = new ContentValues();
contentValues1.put("content",mWorkingNote.mContent);
contentResolver.update(Uri.parse("content://micode_notes/data"), contentValues1,"mime_type=? and note_id=?", new String[]{"vnd.android.cursor.item/text_note",""+id});
}else{
Toast.makeText(NoteEditActivity.this, "获取图片失败", Toast.LENGTH_SHORT).show();
}
break;
default:
break;
}
}
//获取文件的real path
public String getPath(final Context context, final Uri uri) {
final boolean isKitKat = Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT;
// DocumentProvider
if (isKitKat && DocumentsContract.isDocumentUri(context, uri)) {
if (isMediaDocument(uri)) {
final String docId = DocumentsContract.getDocumentId(uri);
final String[] split = docId.split(":");
final String type = split[0];
Uri contentUri = null;
if ("image".equals(type)) {
contentUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
}
final String selection = "_id=?";
final String[] selectionArgs = new String[]{split[1]};
return getDataColumn(context, contentUri, selection, selectionArgs);
}
}
// Media
else if ("content".equalsIgnoreCase(uri.getScheme())) {
return getDataColumn(context, uri, null, null);
}
// File
else if ("file".equalsIgnoreCase(uri.getScheme())) {
return uri.getPath();
}
return null;
}
//获取数据列_获取此 Uri 的数据列的值。这对MediaStore Uris 和其他基于文件的 ContentProvider。
public String getDataColumn(Context context, Uri uri, String selection, String[] selectionArgs) {
Cursor cursor = null;
final String column = "_data";
final String[] projection = {column};
try {
cursor = context.getContentResolver().query(uri, projection, selection, selectionArgs, null);
if (cursor != null && cursor.moveToFirst()) {
final int column_index = cursor.getColumnIndexOrThrow(column);
return cursor.getString(column_index);
}
} finally {
if (cursor != null)
cursor.close();
}
return null;
}
//是否为媒体文件
public boolean isMediaDocument(Uri uri) {
return "com.android.providers.media.documents".equals(uri.getAuthority());
}
//*********
/**
* @description :便
* @param 1:
* @param 2:
* @param 3:
* @return :void
* @author zhangchaoqun
*/
private void initEditText() {
InputStream in = null;
//根据传入值的不同类型,加载不同的文字到便签中
switch (getIntent().getIntExtra("open_mode", 0)) {
case 1://创建事件便签
in = getResources().openRawResource(R.raw.event);
break;
case 2://创建联系人便签
in = getResources().openRawResource(R.raw.contact);
break;
default://创建普通便签
break;
}
//下面一段代码基本是仿照setAppInfoFromRawRes方法从资源里添加文本
if (in == null) return;
Editable edit = mNoteEditor.getText();
StringBuilder sb = new StringBuilder();//代表一个字符序列可变的字符串
try (InputStreamReader isr = new InputStreamReader(in); BufferedReader br = new BufferedReader(isr);) {
//使用指定的字符集读取字节并将它们解码为字符
//缓冲区流读入
char[] buf = new char[1024];
int len = 0;
while ((len = br.read(buf)) > 0) {//read读取一个字符若读取到末尾则返回-1这里是加载到buf中
sb.append(buf, 0, len);//从buf里0开始的len长度的字符串加载到sb后
}
} catch (IOException e) {
e.printStackTrace();
}
edit.append(sb.toString());
mNoteEditor.setText(edit);
if (in != null) {
try {
in.close();
} catch (IOException e) {
Log.e(TAG, "initEditText " + e.toString());
}
}
}
//录音
private void insertRecord(){
Intent intent = new Intent(this, RecordActivity.class);
startActivityForResult(intent, REQUEST_CODE_RECORD);
}
}

@ -40,6 +40,7 @@ public class NoteItemData {
NoteColumns.TYPE,
NoteColumns.WIDGET_ID,
NoteColumns.WIDGET_TYPE,
// NoteColumns.TOP
};
private static final int ID_COLUMN = 0;
@ -54,6 +55,7 @@ public class NoteItemData {
private static final int TYPE_COLUMN = 9;
private static final int WIDGET_ID_COLUMN = 10;
private static final int WIDGET_TYPE_COLUMN = 11;
//private static final int TOP = 12;
private long mId;
private long mAlertDate;
@ -76,6 +78,8 @@ public class NoteItemData {
private boolean mIsOneNoteFollowingFolder;
private boolean mIsMultiNotesFollowingFolder;
private String mTop;
public NoteItemData(Context context, Cursor cursor) {
mId = cursor.getLong(ID_COLUMN);
mAlertDate = cursor.getLong(ALERTED_DATE_COLUMN);

@ -19,6 +19,7 @@ package net.micode.notes.ui;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
import android.app.SearchManager;
import android.appwidget.AppWidgetManager;
import android.content.AsyncQueryHandler;
import android.content.ContentResolver;
@ -92,6 +93,10 @@ import java.util.HashSet;
* @version: v1.0
*/
public class NotesListActivity extends Activity implements OnClickListener, OnItemLongClickListener {
public static int secret_mode = 0;//私密模式的标志位为1则代表进入了私密模式
public static int login_mode = 0;//是否设置了密码0表示还没有设置1表示已经设置了密码
private static final int FOLDER_NOTE_LIST_QUERY_TOKEN = 0;
private static final int FOLDER_LIST_QUERY_TOKEN = 1;
@ -149,6 +154,11 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
private final static int REQUEST_CODE_NEW_NODE = 103;
private AlertDialog alertDialog1;
private final static String SEARCH_RESULTS = "搜索关键字:";
/**
* @description :
* @param 1:savedInstanceState
@ -246,8 +256,17 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
@Override
protected void onStart() {
super.onStart();
Intent intent=getIntent();
if(Intent.ACTION_SEARCH.equals(intent.getAction())){
String query = intent.getStringExtra(SearchManager.QUERY);
mTitleBar.setText(SEARCH_RESULTS+query);
mTitleBar.setVisibility(View.VISIBLE);
mAddNewNote.setVisibility(View.GONE);
startAsyncNotesSearchListQuery(query);
} else{
startAsyncNotesListQuery();
}
}
private void initResources() {
mContentResolver = this.getContentResolver();
@ -328,6 +347,7 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
// TODO Auto-generated method stub
return false;
}
@ -446,15 +466,59 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
};
/**
* @description :便
* @param 1:
* @param 2:
* @param 3:
* @return :void
* @author zhangchaoqun
*/
private void startAsyncNotesListQuery() {
String selection = (mCurrentFolderId == Notes.ID_ROOT_FOLDER) ? ROOT_FOLDER_SELECTION
: NORMAL_SELECTION;
/*
mBackgroundQueryHandler.startQuery(FOLDER_NOTE_LIST_QUERY_TOKEN, null,
Notes.CONTENT_NOTE_URI, NoteItemData.PROJECTION, selection, new String[] {
String.valueOf(mCurrentFolderId)
}, NoteColumns.TYPE + " DESC," + NoteColumns.MODIFIED_DATE + " DESC");
*/
//功能添加:私密模式
if(secret_mode == 0) {//非私密模式则正常按照原来的方式进行运行
mBackgroundQueryHandler.startQuery(FOLDER_NOTE_LIST_QUERY_TOKEN, null,
Notes.CONTENT_NOTE_URI, NoteItemData.PROJECTION, selection, new String[] {
String.valueOf(mCurrentFolderId)
}, NoteColumns.TYPE + " DESC," + NoteColumns.MODIFIED_DATE + " DESC" );//NoteColumns.TOP +
}
else{//私密模式则把便签的标题显示改为自己想要的某一值,不显示便签内容
String str1 = "00000";
String [] PROJECTION = new String [] { //定义一个新的PROJECTION数组只换掉SNIPPET
NoteColumns.ID,
NoteColumns.ALERTED_DATE,
NoteColumns.BG_COLOR_ID,
NoteColumns.CREATED_DATE,
NoteColumns.HAS_ATTACHMENT,
NoteColumns.MODIFIED_DATE,
NoteColumns.NOTES_COUNT,
NoteColumns.PARENT_ID,
//NoteColumns.SNIPPET,
str1,
NoteColumns.TYPE,
NoteColumns.WIDGET_ID,
NoteColumns.WIDGET_TYPE,
// NoteColumns.TOP
};
mBackgroundQueryHandler.startQuery(FOLDER_NOTE_LIST_QUERY_TOKEN, null,
Notes.CONTENT_NOTE_URI, PROJECTION, selection, new String[]{
String.valueOf(mCurrentFolderId)
}, NoteColumns.TYPE + " DESC," + NoteColumns.MODIFIED_DATE + " DESC");
}
}
private final class BackgroundQueryHandler extends AsyncQueryHandler {
public BackgroundQueryHandler(ContentResolver contentResolver) {
super(contentResolver);
@ -500,9 +564,10 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
builder.show();
}
private void createNewNote() {
private void createNewNote(int openMode) {
Intent intent = new Intent(this, NoteEditActivity.class);
intent.setAction(Intent.ACTION_INSERT_OR_EDIT);
intent.putExtra("open_mode",openMode);//不同的打开方式,加载不同的便签模板
intent.putExtra(Notes.INTENT_EXTRA_FOLDER_ID, mCurrentFolderId);
this.startActivityForResult(intent, REQUEST_CODE_NEW_NODE);
}
@ -597,7 +662,8 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
public void onClick(View v) {
if (v.getId() == R.id.btn_new_note) {
createNewNote();
chooseNoteType();
//createNewNote();
}
}
@ -796,6 +862,7 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
@Override
public boolean onPrepareOptionsMenu(Menu menu) {
menu.clear();
if (mState == ListEditState.NOTE_LIST) {
getMenuInflater().inflate(R.menu.note_list, menu);
@ -809,6 +876,12 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
} else {
Log.e(TAG, "Wrong state:" + mState);
}
//功能添加:私密模式
if(secret_mode == 1)
menu.findItem(R.id.menu_secret).setVisible(false);
else
menu.findItem(R.id.menu_quit_secret).setVisible(false);
return true;
}
@ -832,13 +905,82 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
} else if (itemId == R.id.menu_setting) {
startPreferenceActivity();
} else if (itemId == R.id.menu_new_note) {
createNewNote();
} else if (itemId == R.id.menu_search) {
createNewNote(0);
} else if(itemId==R.id.menu_secret){ //进入私密模式
AlertDialog.Builder dialog = new AlertDialog.Builder(NotesListActivity.this);
dialog.setTitle("注意!");
dialog.setMessage("您确认进入私密模式吗?");
dialog.setCancelable(false);
dialog.setPositiveButton("确认", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
secret_mode = 1;
startAsyncNotesListQuery();
Toast.makeText(NotesListActivity.this, "您已进入私密模式", Toast.LENGTH_SHORT).show();
}
});
dialog.setNegativeButton("取消", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
}
});
dialog.show();
startAsyncNotesListQuery();
Toast.makeText(this, "您已进入私密模式", Toast.LENGTH_SHORT).show();
} else if(itemId==R.id.menu_quit_secret){ //退出私密模式
AlertDialog.Builder dialog = new AlertDialog.Builder(NotesListActivity.this);
dialog.setTitle("注意!");
dialog.setMessage("您确认退出私密模式吗?");
dialog.setCancelable(false);
dialog.setPositiveButton("确认", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
secret_mode = 0;
startAsyncNotesListQuery();
Toast.makeText(NotesListActivity.this,"您已退出私密模式",Toast.LENGTH_SHORT).show();
}
});
dialog.setNegativeButton("取消", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which){}
});
dialog.show();
}else if(itemId==R.id.menu_search){//搜索按钮的响应
onSearchRequested();
} else if(itemId==R.id.menu_login){//设置密码登录功能
if(login_mode==0)//还没有设置密码
setLoginPassword();
else if(login_mode==1)//已经设置密码
changeLoginPassword();
}else if(itemId==R.id.menu_login_delete){//删除密码
deleteLoginPassword();
}
return true;
}
//设置登录密码
private void setLoginPassword() {
login_mode=1;
Intent intent=new Intent(NotesListActivity.this,RegisterLoginPassword.class);
startActivity(intent);
finish();
}
//改变登录密码
private void changeLoginPassword() {
Intent intent=new Intent(NotesListActivity.this,ChangedLoginPassword.class);
startActivity(intent);
finish();
}
//删除登录密码
private void deleteLoginPassword(){
login_mode=0;
Intent intent=new Intent(NotesListActivity.this,DeleteLoginPassword.class);
startActivity(intent);
finish();
}
@Override
public boolean onSearchRequested() {
startSearch(null, false, null /* appData */, false);
@ -972,4 +1114,43 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
}
return false;
}
//便签模板
public void chooseNoteType(){
final String[] items = {"普通便签", "事件便签", "联系人便签"};
AlertDialog.Builder alertBuilder = new AlertDialog.Builder(this);
alertBuilder.setTitle("选择创建的便签");
alertBuilder.setItems(items, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) {
//对createNewNote方法进行了调用
// 参数i即使代表所选单选按钮的排列次序也代表打开便签模板的类型
createNewNote(i);
Toast.makeText(NotesListActivity.this, items[i], Toast.LENGTH_SHORT).show();
alertDialog1.dismiss();
}
});
alertDialog1 = alertBuilder.create();
alertDialog1.show();
}
/**
* @description :便
* @param 1:query
* @param 2:
* @param 3:
* @return :void
* @author zhangchaoqun
*/
private void startAsyncNotesSearchListQuery(String query){
String selection = NoteColumns.SNIPPET+" LIKE'%"+query+"%'";//模糊搜索
mBackgroundQueryHandler.startQuery(FOLDER_NOTE_LIST_QUERY_TOKEN,null,
Notes.CONTENT_NOTE_URI,
NoteItemData.PROJECTION,
selection,
null,
NoteColumns.TYPE+" DESC,"+NoteColumns.MODIFIED_DATE+" DESC");
}
}

@ -0,0 +1,174 @@
package net.micode.notes.ui;
import static net.micode.notes.R.id.start_record;
import android.app.Activity;
import android.media.MediaRecorder;
import android.os.Bundle;
import android.os.Environment;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;
import net.micode.notes.R;
import java.io.File;
import java.io.IOException;
public class RecordActivity extends Activity {
private MediaRecorder mediaRecorder;
private String TAG = "RecordActivity";
private boolean isRecording;
private Button start;
private Button stop;
private Button play;
@Override
protected void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
this.setContentView(R.layout.record_activity);
start = (Button) findViewById (start_record);
stop = (Button) findViewById (R.id.stop_record);
play = (Button) findViewById (R.id.play_record);
start.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
start();
Log.d(TAG, "onClick: Start");
}
});
stop.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
stop();
Log.d(TAG, "onClick: Stop");
}
});
play.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Log.d(TAG, "onClick: play");
}
});
}
//在这里重载Back键执行的操作
/*@Override
public void onBackPressed(){
}*/
private boolean checkSDCard() {
// TODO Auto-generated method stub
//检测SD卡是否插入手机中
if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
return true;
}
return false;
}
/**
*
*/
protected void start() {
try {
File path;
if (checkSDCard()) {
File mpath = Environment.getExternalStorageDirectory();
path = new File(mpath.getPath() + File.separator + "audioRecords");
Log.d(TAG, "start: "+path);
if (!path.mkdirs()) {
Log.d("audioRecorder", "创建目录失败");
return;
}
} else {
Toast.makeText(RecordActivity.this, "SDcard未连接",
Toast.LENGTH_LONG).show();
return;
}
File file = null;
try {
file = File.createTempFile(String.valueOf("myrecord_"), ".amr", path);
} catch (IOException e) {
Log.d("audioRecorder", "文件创建失败");
}
if (file.exists()) {
// 如果文件存在,删除它,演示代码保证设备上只有一个录音文件
file.delete();
}
mediaRecorder = new MediaRecorder();
// 设置音频录入源
mediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
// 设置录制音频的输出格式
mediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
// 设置音频的编码格式
mediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
// 设置录制音频文件输出文件路径
mediaRecorder.setOutputFile(file.getAbsolutePath());
mediaRecorder.setOnErrorListener(new MediaRecorder.OnErrorListener() {
@Override
public void onError(MediaRecorder mr, int what, int extra) {
// 发生错误,停止录制
mediaRecorder.stop();
mediaRecorder.release();
mediaRecorder = null;
isRecording=false;
start.setEnabled(true);
stop.setEnabled(false);
Toast.makeText(RecordActivity.this, "录音发生错误", Toast.LENGTH_SHORT).show();
}
});
// 准备、开始
mediaRecorder.prepare();
mediaRecorder.start();
isRecording=true;
start.setEnabled(false);
stop.setEnabled(true);
Toast.makeText(RecordActivity.this, "开始录音", Toast.LENGTH_SHORT).show();
} catch (Exception e) {
e.printStackTrace();
}
}
/**
*
*/
protected void stop() {
if (isRecording) {
// 如果正在录音,停止并释放资源
mediaRecorder.stop();
mediaRecorder.release();
mediaRecorder = null;
isRecording=false;
start.setEnabled(true);
stop.setEnabled(false);
Toast.makeText(RecordActivity.this, "录音结束", Toast.LENGTH_SHORT).show();
}
}
@Override
protected void onDestroy() {
if (isRecording) {
// 如果正在录音,停止并释放资源
mediaRecorder.stop();
mediaRecorder.release();
mediaRecorder = null;
}
super.onDestroy();
}
}

@ -0,0 +1,65 @@
package net.micode.notes.ui;
import android.app.Activity;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.view.WindowManager;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;
import net.micode.notes.R;
public class RegisterLoginPassword extends Activity{
EditText password01;
EditText password02;
Button registered;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_set_loginpassword);
getWindow().setSoftInputMode(
WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE
| WindowManager.LayoutParams.SOFT_INPUT_STATE_VISIBLE);
password01=(EditText) findViewById(R.id.rg_password01);
password02=(EditText) findViewById(R.id.rg_password02);
registered=(Button)findViewById(R.id.rg_registered);
registered.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
String text02 = password01.getText().toString();
String text03 = password02.getText().toString();
if(text02.equals("")==true) {
Toast.makeText(RegisterLoginPassword.this, "密码不能为空", Toast.LENGTH_SHORT).show();
}else if (text02.equals(text03) == false) {
Toast.makeText(RegisterLoginPassword.this, "密码不匹配,请重新输入密码", Toast.LENGTH_SHORT).show();
password02.setText("");
}else if (text02.equals(text03) == true){
SharedPreferences.Editor editor=getSharedPreferences("user management",
MODE_PRIVATE).edit();
editor.putBoolean("user",true);//true表示已经设置登录密码
editor.putString("password",text02);
editor.apply();
Log.d("RegisterLoginPassword","password is "+text02);
Toast.makeText(RegisterLoginPassword.this, "设置密码成功", Toast.LENGTH_SHORT).show();
Intent intent=new Intent(RegisterLoginPassword.this,NotesListActivity.class);
startActivity(intent);
finish();
}
}
});
}
@Override
public void onBackPressed() {
Intent intent=new Intent(RegisterLoginPassword.this,NotesListActivity.class);
startActivity(intent);
finish();
}
}

@ -0,0 +1,49 @@
package net.micode.notes.ui;
import android.content.Intent;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.os.Handler;
import android.content.Intent;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.os.Handler;
import net.micode .notes.R;
import net.micode.notes.databinding.ActivitySplashBinding;
import net.micode.notes.R;
/**
* @projectName: xiaomi label
* @package: ui
* @className: type_name
* @description:
* @author: zhangchaoqun
* @createDate: datetime
* @updateUser: user
* @updateDate: datetime
* @updateRemark:
* @version: v1.0
*/
public class SplashActivity extends AppCompatActivity {
Handler mHandler=new Handler();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); //加载启动界面
setContentView(R.layout.activity_splash); //加载启动图片
// 当计时结束时跳转至NotesListActivity
mHandler.postDelayed(new Runnable() {
@Override
public void run() {
Intent intent=new Intent();
intent.setClass(SplashActivity.this, NotesListActivity.class);
startActivity(intent);
finish(); //销毁欢迎页面
}
}, 1000); // 1秒后跳转
}
}

@ -0,0 +1,48 @@
@startuml
'https://plantuml.com/class-diagram
class net.micode.notes.ui.NoteItemData
class net.micode.notes.ui.FoldersListAdapter
class net.micode.notes.ui.NotesListItem
class net.micode.notes.ui.AlarmInitReceiver
class net.micode.notes.ui.DateTimePickerDialog
class net.micode.notes.ui.NotesListActivity
class net.micode.notes.ui.NotesPreferenceActivity
class net.micode.notes.ui.RegisterLoginPassword
class net.micode.notes.ui.AlarmAlertActivity
class net.micode.notes.ui.DeleteLoginPassword
class net.micode.notes.ui.RecordActivity
class net.micode.notes.ui.DropdownMenu
class net.micode.notes.ui.NoteEditText
class net.micode.notes.ui.DateTimePicker
class net.micode.notes.ui.LoginActivity
class net.micode.notes.ui.NoteEditActivity
class net.micode.notes.ui.NotesListAdapter
class net.micode.notes.ui.AlarmReceiver
class net.micode.notes.ui.ChangedLoginPassword
class net.micode.notes.ui.SplashActivity
net.micode.notes.ui.NotesListActivity --> net.micode.notes.ui.NotesPreferenceActivity
net.micode.notes.ui.NotesListActivity --> net.micode.notes.ui.DropdownMenu
net.micode.notes.ui.NotesListActivity --> net.micode.notes.ui.FoldersListAdapter
net.micode.notes.ui.NoteItemData--|>net.micode.notes.ui.NotesListActivity
net.micode.notes.ui.NotesListAdapter--|>net.micode.notes.ui.NotesListActivity
net.micode.notes.ui.NotesListAdapter-->net.micode.notes.ui.NotesListItem
net.micode.notes.ui.NoteEditActivity-->net.micode.notes.ui.NotesPreferenceActivity
net.micode.notes.ui.NoteEditActivity-->net.micode.notes.ui.AlarmReceiver
net.micode.notes.ui.NoteEditActivity-->net.micode.notes.ui.DateTimePickerDialog
net.micode.notes.ui.NoteEditActivity-->net.micode.notes.ui.NoteEditText
net.micode.notes.ui.AlarmInitReceiver-->net.micode.notes.ui.AlarmReceiver
net.micode.notes.ui.AlarmReceiver-->net.micode.notes.ui.AlarmAlertActivity
net.micode.notes.ui.DateTimePicker--|>net.micode.notes.ui.DateTimePickerDialog
net.micode.notes.ui.ChangedLoginPassword--net.micode.notes.ui.DeleteLoginPassword
net.micode.notes.ui.ChangedLoginPassword--net.micode.notes.ui.LoginActivity
net.micode.notes.ui.LoginActivity--net.micode.notes.ui.DeleteLoginPassword
net.micode.notes.ui.LoginActivity--net.micode.notes.ui.RegisterLoginPassword
net.micode.notes.ui.RegisterLoginPassword--net.micode.notes.ui.DeleteLoginPassword
net.micode.notes.ui.RegisterLoginPassword--net.micode.notes.ui.ChangedLoginPassword
@enduml

@ -0,0 +1,22 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (c) 2010-2011, The MiCode Open Source Community (www.micode.net)
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_pressed="true" android:color="#88555555" />
<item android:state_selected="true" android:color="#ff999999" />
<item android:color="#ff000000" />
</selector>

@ -0,0 +1,20 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (c) 2010-2011, The MiCode Open Source Community (www.micode.net)
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:color="#50000000" />
</selector>

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 245 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 443 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 554 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

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

Loading…
Cancel
Save