diff --git a/app/src/main/ic_launcher-web.png b/app/src/main/ic_launcher-web.png index c4fde43..8a1ffe8 100644 Binary files a/app/src/main/ic_launcher-web.png and b/app/src/main/ic_launcher-web.png differ diff --git a/app/src/main/java/com/github/axet/audiorecorder/activities/MainActivity.java b/app/src/main/java/com/github/axet/audiorecorder/activities/MainActivity.java index a8a2c70..f2a0f0a 100644 --- a/app/src/main/java/com/github/axet/audiorecorder/activities/MainActivity.java +++ b/app/src/main/java/com/github/axet/audiorecorder/activities/MainActivity.java @@ -1,6 +1,7 @@ package com.github.axet.audiorecorder.activities; import android.Manifest; +import android.content.Context; import android.content.Intent; import android.content.SharedPreferences; import android.content.pm.PackageManager; @@ -11,80 +12,101 @@ import android.support.v4.app.ActivityCompat; import android.support.v4.content.ContextCompat; import android.support.v7.app.AppCompatActivity; import android.support.v7.widget.Toolbar; +import android.util.Log; import android.view.LayoutInflater; import android.view.Menu; import android.view.MenuItem; import android.view.View; import android.view.ViewGroup; +import android.widget.AbsListView; import android.widget.AdapterView; +import android.widget.ArrayAdapter; import android.widget.ListAdapter; import android.widget.ListView; +import android.widget.TextView; import android.widget.Toast; import com.github.axet.audiorecorder.R; +import com.github.axet.audiorecorder.animations.RecordingAnimation; +import com.github.axet.audiorecorder.app.Storage; -public class MainActivity extends AppCompatActivity { +import java.io.File; +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Date; - Recordings recordings = new Recordings(); +public class MainActivity extends AppCompatActivity implements AbsListView.OnScrollListener{ + static final int TYPE_COLLAPSED = 0; + static final int TYPE_EXPANDED = 1; + static final int TYPE_DELETED = 2; - public class Recordings implements ListAdapter { + final int[] ALL = {TYPE_COLLAPSED, TYPE_EXPANDED}; - @Override - public boolean areAllItemsEnabled() { - return true; + int selected; + + int scrollState; + + Recordings recordings; + Storage storage; + ListView list; + + public class Recordings extends ArrayAdapter { + + public Recordings(Context context) { + super(context, 0); } @Override - public boolean isEnabled(int position) { - return true; - } + public View getView(final int position, View convertView, ViewGroup parent) { + LayoutInflater inflater = LayoutInflater.from(getContext()); - @Override - public void registerDataSetObserver(DataSetObserver observer) { - } + if (convertView == null) { + convertView = inflater.inflate(R.layout.recording, parent, false); + convertView.setTag(-1); + } - @Override - public void unregisterDataSetObserver(DataSetObserver observer) { - } + File f = getItem(position); - @Override - public int getCount() { - return 0; - } + TextView title = (TextView) convertView.findViewById(R.id.recording_title); + title.setText(f.getName()); - @Override - public Object getItem(int position) { - return null; - } + SimpleDateFormat s = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); + TextView time = (TextView) convertView.findViewById(R.id.recording_time); + time.setText(s.format(new Date(f.lastModified()))); - @Override - public long getItemId(int position) { - return 0; - } + View player = convertView.findViewById(R.id.recording_player); + player.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + } + }); - @Override - public boolean hasStableIds() { - return false; - } + if(selected == position) { + RecordingAnimation.apply(list, convertView, true, scrollState == SCROLL_STATE_IDLE && (int) convertView.getTag() == TYPE_COLLAPSED); + convertView.setTag(TYPE_EXPANDED); - @Override - public View getView(int position, View convertView, ViewGroup parent) { - return null; - } + convertView.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + selected = -1; + notifyDataSetChanged(); + } + }); + }else { + RecordingAnimation.apply(list, convertView, false, scrollState == SCROLL_STATE_IDLE && (int) convertView.getTag() == TYPE_EXPANDED); + convertView.setTag(TYPE_COLLAPSED); - @Override - public int getItemViewType(int position) { - return 0; - } + convertView.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + selected = position; + notifyDataSetChanged(); + } + }); + } - @Override - public int getViewTypeCount() { - return 1; - } - - @Override - public boolean isEmpty() { - return getCount() == 0; + return convertView; } } @@ -106,8 +128,8 @@ public class MainActivity extends AppCompatActivity { } }); - ListView list = (ListView) findViewById(R.id.list); - list.setAdapter(recordings); + list = (ListView) findViewById(R.id.list); + list.setOnScrollListener(this); list.setEmptyView(findViewById(R.id.empty_list)); if (permitted()) @@ -116,7 +138,22 @@ public class MainActivity extends AppCompatActivity { // load recordings void load() { + storage = new Storage(this); + File f = storage.getStoragePath(); + File[] ff = f.listFiles(); + + ArrayList a = null; + + if (ff != null) { + a = new ArrayList(Arrays.asList(ff)); + } else { + a = new ArrayList(); + } + + recordings = new Recordings(this); + recordings.addAll(a); + list.setAdapter(recordings); } @Override @@ -145,6 +182,14 @@ public class MainActivity extends AppCompatActivity { return super.onOptionsItemSelected(item); } + @Override + protected void onResume() { + super.onResume(); + + if (permitted(PERMISSIONS)) + load(); + } + @Override public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) { super.onRequestPermissionsResult(requestCode, permissions, grantResults); @@ -177,4 +222,13 @@ public class MainActivity extends AppCompatActivity { } return true; } + + @Override + public void onScrollStateChanged(AbsListView view, int scrollState) { + this.scrollState = scrollState; + } + + @Override + public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) { + } } diff --git a/app/src/main/java/com/github/axet/audiorecorder/animations/RecordingAnimation.java b/app/src/main/java/com/github/axet/audiorecorder/animations/RecordingAnimation.java index 648dc87..76367f3 100644 --- a/app/src/main/java/com/github/axet/audiorecorder/animations/RecordingAnimation.java +++ b/app/src/main/java/com/github/axet/audiorecorder/animations/RecordingAnimation.java @@ -33,7 +33,7 @@ public class RecordingAnimation extends MarginAnimation { } public RecordingAnimation(ListView list, View v, boolean expand) { - super(v.findViewById(R.id.recording_detail), expand); + super(v.findViewById(R.id.recording_player), expand); handler = new Handler(); diff --git a/app/src/main/java/com/github/axet/audiorecorder/widgets/OpenFileDialog.java b/app/src/main/java/com/github/axet/audiorecorder/widgets/OpenFileDialog.java index f67f2c4..f54f92d 100644 --- a/app/src/main/java/com/github/axet/audiorecorder/widgets/OpenFileDialog.java +++ b/app/src/main/java/com/github/axet/audiorecorder/widgets/OpenFileDialog.java @@ -10,9 +10,13 @@ import android.graphics.drawable.Drawable; import android.os.Environment; import android.preference.EditTextPreference; import android.util.DisplayMetrics; +import android.util.Log; import android.util.TypedValue; import android.view.Display; import android.view.Gravity; +import android.view.Menu; +import android.view.MenuInflater; +import android.view.MenuItem; import android.view.View; import android.view.ViewGroup; import android.view.WindowManager; @@ -22,9 +26,12 @@ import android.widget.Button; import android.widget.EditText; import android.widget.LinearLayout; import android.widget.ListView; +import android.widget.PopupMenu; import android.widget.TextView; import android.widget.Toast; +import com.github.axet.audiorecorder.R; + import java.io.File; import java.io.FilenameFilter; import java.util.ArrayList; @@ -42,7 +49,6 @@ public class OpenFileDialog extends AlertDialog.Builder { private Drawable folderIcon; private Drawable fileIcon; private Drawable upIcon; - private String accessDeniedMessage; FileAdapter adapter; public interface OpenDialogListener { @@ -110,20 +116,20 @@ public class OpenFileDialog extends AlertDialog.Builder { linearLayout.addView(createBackItem(context)); listView = createListView(context); linearLayout.addView(listView); - setCustomTitle(title) - .setView(linearLayout) - .setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int which) { - if (listener != null) { - if (selectedIndex > -1) - listener.onFileSelected(listView.getItemAtPosition(selectedIndex).toString()); - else - listener.onFileSelected(currentPath.toString()); - } - } - }) - .setNegativeButton(android.R.string.cancel, null); + setCustomTitle(title); + setView(linearLayout); + setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + if (listener != null) { + if (selectedIndex > -1) + listener.onFileSelected(listView.getItemAtPosition(selectedIndex).toString()); + else + listener.onFileSelected(currentPath.toString()); + } + } + }); + setNegativeButton(android.R.string.cancel, null); } @Override @@ -172,11 +178,6 @@ public class OpenFileDialog extends AlertDialog.Builder { return this; } - public OpenFileDialog setAccessDeniedMessage(String message) { - this.accessDeniedMessage = message; - return this; - } - private static Display getDefaultDisplay(Context context) { return ((WindowManager) context.getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay(); } @@ -255,22 +256,45 @@ public class OpenFileDialog extends AlertDialog.Builder { return ll; } + public interface EditClick { + public void click(String text); + } + + AlertDialog.Builder createEditDialog(Context context, String title, String value, final EditClick ok) { + AlertDialog.Builder builder = new AlertDialog.Builder(context); + LinearLayout ll = new LinearLayout(context); + ll.setOrientation(LinearLayout.VERTICAL); + TextView text = createTitle(context); + text.setText(title); + ll.addView(text); + final EditText input = new EditText(context); + input.setText(value); + ll.addView(input); + builder.setView(ll); + builder.setPositiveButton("Ok", new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, int whichButton) { + ok.click(input.getText().toString().trim()); + } + }); + builder.setNegativeButton("Cancel", new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, int whichButton) { + dialog.cancel(); + } + }); + return builder; + } + private TextView createNewFolder(final Context context) { Button textView = new Button(context); textView.setPadding(15, 0, 15, 0); textView.setText("New Folder"); textView.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT)); textView.setOnClickListener(new View.OnClickListener() { - @Override public void onClick(View view) { - EditTextPreference edit = new EditTextPreference(getContext()); - AlertDialog.Builder builder = new AlertDialog.Builder(getContext()); - final EditText input = new EditText(getContext()); - builder.setView(input); - builder.setPositiveButton("Ok", new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, int whichButton) { - String value = input.getText().toString().trim(); + AlertDialog.Builder builder = createEditDialog(context, "Folder Name", "", new EditClick() { + @Override + public void click(String value) { File f = new File(currentPath, value); if (!f.mkdir()) { Toast.makeText(context, "Unable create folder: '" + value + "'", Toast.LENGTH_SHORT).show(); @@ -278,11 +302,6 @@ public class OpenFileDialog extends AlertDialog.Builder { RebuildFiles(); } }); - builder.setNegativeButton("Cancel", new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, int whichButton) { - dialog.cancel(); - } - }); builder.show(); } }); @@ -331,8 +350,46 @@ public class OpenFileDialog extends AlertDialog.Builder { changeTitle(); } - private ListView createListView(Context context) { + public static final String RENAME = "Rename"; + public static final String DELETE = "Delete"; + + private ListView createListView(final Context context) { ListView listView = new ListView(context); + listView.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() { + @Override + public boolean onItemLongClick(AdapterView parent, View view, final int position, long id) { + PopupMenu p = new PopupMenu(context, view); + p.getMenu().add(RENAME); + p.getMenu().add(DELETE); + p.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() { + @Override + public boolean onMenuItemClick(MenuItem item) { + if (item.getTitle().equals(RENAME)) { + final File ff = (File) adapter.getItem(position); + AlertDialog.Builder b = createEditDialog(context, "Folder Name", ff.getName(), new EditClick() { + @Override + public void click(String text) { + File f = new File(ff.getParent(), text); + ff.renameTo(f); + RebuildFiles(); + } + }); + b.show(); + return true; + } + if (item.getTitle().equals(DELETE)) { + File ff = (File) adapter.getItem(position); + ff.delete(); + RebuildFiles(); + return true; + } + return false; + } + }); + p.show(); + return true; + } + }); listView.setOnItemClickListener(new AdapterView.OnItemClickListener() { @Override diff --git a/app/src/main/java/com/github/axet/audiorecorder/widgets/StoragePathPreference.java b/app/src/main/java/com/github/axet/audiorecorder/widgets/StoragePathPreference.java index 41f12b4..9119ec3 100644 --- a/app/src/main/java/com/github/axet/audiorecorder/widgets/StoragePathPreference.java +++ b/app/src/main/java/com/github/axet/audiorecorder/widgets/StoragePathPreference.java @@ -52,6 +52,9 @@ public class StoragePathPreference extends EditTextPreference { f.setOpenDialogListener(new OpenFileDialog.OpenDialogListener() { @Override public void onFileSelected(String fileName) { + File f = new File(fileName); + if (!f.isDirectory()) + fileName = f.getParent(); if (callChangeListener(fileName)) { setText(fileName); } @@ -68,4 +71,9 @@ public class StoragePathPreference extends EditTextPreference { } return s; } + + @Override + protected void onRestoreInstanceState(Parcelable state) { + super.onRestoreInstanceState(state); + } } diff --git a/app/src/main/res/drawable-hdpi/share.png b/app/src/main/res/drawable-hdpi/share.png new file mode 100644 index 0000000..fb28541 Binary files /dev/null and b/app/src/main/res/drawable-hdpi/share.png differ diff --git a/app/src/main/res/drawable-hdpi/trash.png b/app/src/main/res/drawable-hdpi/trash.png new file mode 100644 index 0000000..1c0d4a0 Binary files /dev/null and b/app/src/main/res/drawable-hdpi/trash.png differ diff --git a/app/src/main/res/drawable-mdpi/share.png b/app/src/main/res/drawable-mdpi/share.png new file mode 100644 index 0000000..0851982 Binary files /dev/null and b/app/src/main/res/drawable-mdpi/share.png differ diff --git a/app/src/main/res/drawable-mdpi/trash.png b/app/src/main/res/drawable-mdpi/trash.png new file mode 100644 index 0000000..f26fc3b Binary files /dev/null and b/app/src/main/res/drawable-mdpi/trash.png differ diff --git a/app/src/main/res/drawable-xhdpi/share.png b/app/src/main/res/drawable-xhdpi/share.png new file mode 100644 index 0000000..95418b6 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/share.png differ diff --git a/app/src/main/res/drawable-xhdpi/trash.png b/app/src/main/res/drawable-xhdpi/trash.png new file mode 100644 index 0000000..1949187 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/trash.png differ diff --git a/app/src/main/res/drawable-xxhdpi/share.png b/app/src/main/res/drawable-xxhdpi/share.png new file mode 100644 index 0000000..6000077 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/share.png differ diff --git a/app/src/main/res/drawable-xxhdpi/trash.png b/app/src/main/res/drawable-xxhdpi/trash.png new file mode 100644 index 0000000..f32286d Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/trash.png differ diff --git a/app/src/main/res/drawable-xxxhdpi/trash.png b/app/src/main/res/drawable-xxxhdpi/trash.png deleted file mode 100644 index a3005aa..0000000 Binary files a/app/src/main/res/drawable-xxxhdpi/trash.png and /dev/null differ diff --git a/app/src/main/res/layout/recording.xml b/app/src/main/res/layout/recording.xml index 808d39d..c467168 100644 --- a/app/src/main/res/layout/recording.xml +++ b/app/src/main/res/layout/recording.xml @@ -4,10 +4,6 @@ android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical" - android:paddingBottom="@dimen/activity_vertical_margin" - android:paddingLeft="@dimen/activity_horizontal_margin" - android:paddingRight="@dimen/activity_horizontal_margin" - android:paddingTop="@dimen/activity_vertical_margin" tools:context=".activities.RecordingActivity"> + android:padding="5dp" + android:text="2016-02-01.wav" + android:textSize="20dp" /> @@ -39,13 +39,17 @@ android:orientation="vertical"> @@ -54,24 +58,72 @@ android:layout_width="match_parent" android:layout_height="wrap_content"> - + android:layout_marginLeft="5dp" + android:layout_marginRight="5dp" + android:background="#dedede" + android:orientation="vertical" + android:padding="5dp"> - + android:gravity="center" + android:orientation="horizontal"> - + + + + + + + + - + android:orientation="horizontal"> + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/mipmap-hdpi/ic_launcher.png b/app/src/main/res/mipmap-hdpi/ic_launcher.png index e6ee3db..c1516f5 100644 Binary files a/app/src/main/res/mipmap-hdpi/ic_launcher.png and b/app/src/main/res/mipmap-hdpi/ic_launcher.png differ diff --git a/app/src/main/res/mipmap-mdpi/ic_launcher.png b/app/src/main/res/mipmap-mdpi/ic_launcher.png index 47438e8..42d0d54 100644 Binary files a/app/src/main/res/mipmap-mdpi/ic_launcher.png and b/app/src/main/res/mipmap-mdpi/ic_launcher.png differ diff --git a/app/src/main/res/mipmap-xhdpi/ic_launcher.png b/app/src/main/res/mipmap-xhdpi/ic_launcher.png index b814479..1ada00e 100644 Binary files a/app/src/main/res/mipmap-xhdpi/ic_launcher.png and b/app/src/main/res/mipmap-xhdpi/ic_launcher.png differ diff --git a/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/app/src/main/res/mipmap-xxhdpi/ic_launcher.png index 5ba5953..d5f0440 100644 Binary files a/app/src/main/res/mipmap-xxhdpi/ic_launcher.png and b/app/src/main/res/mipmap-xxhdpi/ic_launcher.png differ diff --git a/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png index 8801dec..df019cf 100644 Binary files a/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png and b/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png differ