diff --git a/app/build.gradle b/app/build.gradle index 812b4f4..baef965 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -21,8 +21,8 @@ android { defaultConfig { applicationId 'org.openintents.convertcsv' - versionCode 13 - versionName '2.0.0-beta1' + versionCode 15 + versionName '2.0.0-beta3' minSdkVersion 19 targetSdkVersion rootProject.ext.targetSdkVersion } diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 393ed21..6f9cef1 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -25,6 +25,7 @@ + android:theme="@style/Theme.AppCompat.NoActionBar"> @@ -138,4 +140,4 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/app/src/main/java/org/openintents/convertcsv/blockstack/AccountActivity.kt b/app/src/main/java/org/openintents/convertcsv/blockstack/AccountActivity.kt index 3d7e941..f59a04d 100644 --- a/app/src/main/java/org/openintents/convertcsv/blockstack/AccountActivity.kt +++ b/app/src/main/java/org/openintents/convertcsv/blockstack/AccountActivity.kt @@ -4,6 +4,7 @@ package org.openintents.convertcsv.blockstack import android.content.Context import android.content.Intent import android.os.Bundle +import android.provider.DocumentsContract import android.support.v4.app.NavUtils import android.support.v7.app.AppCompatActivity import android.util.Log @@ -12,13 +13,10 @@ import android.view.View import android.widget.Toast import kotlinx.android.synthetic.main.activity_account.* import kotlinx.android.synthetic.main.content_account.* -import kotlinx.coroutines.experimental.CommonPool +import kotlinx.coroutines.experimental.* import kotlinx.coroutines.experimental.android.UI -import kotlinx.coroutines.experimental.async -import kotlinx.coroutines.experimental.launch import org.blockstack.android.sdk.BlockstackSession import org.blockstack.android.sdk.Executor -import org.blockstack.android.sdk.PutFileOptions import org.jetbrains.anko.coroutines.experimental.Ref import org.jetbrains.anko.coroutines.experimental.asReference import org.openintents.convertcsv.R @@ -35,14 +33,13 @@ class AccountActivity : AppCompatActivity() { setSupportActionBar(toolbar) supportActionBar!!.setDisplayHomeAsUpEnabled(true) - signInButton.isEnabled = false - signOutButton.isEnabled = false + setLoadingUI(true) val ref: Ref = this.asReference() launch(UI) { - async(CommonPool) { - _blockstackSession = BlockstackSession(ref(), defaultConfig, executor = object: Executor { + async(v8Context) { + _blockstackSession = BlockstackSession(ref(), defaultConfig, executor = object : Executor { override fun onMainThread(function: (Context) -> Unit) { runOnUiThread { function(this@AccountActivity) @@ -54,18 +51,18 @@ class AccountActivity : AppCompatActivity() { async(CommonPool) { function() } - } catch (e:Exception) { + } catch (e: Exception) { Log.d(TAG, "error in network thread", e) } } override fun onV8Thread(function: () -> Unit) { - async(CommonPool) { + runOnV8Thread { function() } } - }) + }, sessionStore = getSessionStore(this@AccountActivity)) if (intent?.action == Intent.ACTION_VIEW) { handleAuthResponse(intent) } @@ -74,39 +71,34 @@ class AccountActivity : AppCompatActivity() { } signInButton.setOnClickListener { _ -> - blockstackSession().redirectUserToSignIn { _ -> - Log.d(TAG, "signed in error!") + launch(UI) { + runOnV8Thread { + blockstackSession().signUserOut() + blockstackSession().redirectUserToSignIn { _ -> + Log.d(TAG, "signed in redirect") + } + } } } signOutButton.setOnClickListener { _ -> launch(UI) { - async(CommonPool) { + runOnV8Thread { blockstackSession().signUserOut() }.await() + notifyDocumentUI() Log.d(TAG, "signed out!") finish() } } - - putFileButton.setOnClickListener { _ -> - launch(UI) { - async(CommonPool) { - blockstackSession().putFile("test.csv", "no data", PutFileOptions(false)) { - Log.d(TAG, "put done " + it.value + " " + it.error) - } - } - } - } } private fun onLoaded() { - signInButton.isEnabled = true - signOutButton.isEnabled = true launch(UI) { - val signedIn = async(CommonPool) { + val signedIn = runOnV8Thread { blockstackSession().isUserSignedIn() }.await() + setLoadingUI(false) if (signedIn) { signInButton.visibility = View.GONE @@ -115,12 +107,23 @@ class AccountActivity : AppCompatActivity() { signInButton.visibility = View.VISIBLE signOutButton.visibility = View.GONE } + notifyDocumentUI() } } private fun onSignIn() { - blockstackSession().loadUserData() - finish() + launch(UI) { + runOnV8Thread { + blockstackSession().loadUserData() + }.await() + notifyDocumentUI() + finish() + } + } + + private fun notifyDocumentUI() { + val rootsUri = DocumentsContract.buildRootsUri("org.openintents.convertcsv.documents") + this@AccountActivity.getContentResolver().notifyChange(rootsUri, null) } override fun onNewIntent(intent: Intent?) { @@ -137,16 +140,37 @@ class AccountActivity : AppCompatActivity() { val authResponse = intent?.data?.getQueryParameter("authResponse") if (authResponse != null) { Log.d(TAG, "authResponse: ${authResponse}") - blockstackSession().handlePendingSignIn(authResponse, { - if (it.hasErrors) { - Toast.makeText(this, it.error, Toast.LENGTH_SHORT).show() - } else { - Log.d(TAG, "signed in!") - runOnUiThread { - onSignIn() - } + setLoadingUI(true) + runOnV8Thread { + try { + Log.d(TAG, "before signed in!") + blockstackSession().handlePendingSignIn(authResponse, { + Log.d(TAG, "signed in result " + it.error + " " + it.value) + if (it.hasErrors) { + Toast.makeText(this@AccountActivity, it.error, Toast.LENGTH_SHORT).show() + } else { + Log.d(TAG, "signed in!") + runOnUiThread { + onSignIn() + } + } + }) + } catch (e: Exception) { + Log.d(TAG, "signed in error", e) } - }) + } + } + } + + private fun setLoadingUI(loading: Boolean) { + if (loading) { + signInButton.isEnabled = false + signOutButton.isEnabled = false + accountDescription.visibility = View.VISIBLE + } else { + signInButton.isEnabled = true + signOutButton.isEnabled = true + accountDescription.visibility = View.INVISIBLE } } @@ -158,14 +182,24 @@ class AccountActivity : AppCompatActivity() { return super.onOptionsItemSelected(item) } + fun runOnV8Thread(runnable: () -> T): Deferred { + return async(v8Context) { + runnable() + } + + } + fun blockstackSession(): BlockstackSession { val session = _blockstackSession if (session != null) { return session } else { + Log.d(TAG, "too early") throw IllegalStateException("No session.") } } } +val v8Context = newFixedThreadPoolContext(1, "v8Thread") + diff --git a/app/src/main/java/org/openintents/convertcsv/blockstack/ConvertCSVProvider.kt b/app/src/main/java/org/openintents/convertcsv/blockstack/ConvertCSVProvider.kt index 16cd6d9..a2b9d18 100644 --- a/app/src/main/java/org/openintents/convertcsv/blockstack/ConvertCSVProvider.kt +++ b/app/src/main/java/org/openintents/convertcsv/blockstack/ConvertCSVProvider.kt @@ -87,7 +87,7 @@ class ConvertCSVProvider : DocumentsProvider() { function.invoke() } } - }) + }, sessionStore = getSessionStore(context)) } mBaseDir = GaiaFile("", true) @@ -113,6 +113,7 @@ class ConvertCSVProvider : DocumentsProvider() { var title: String? = null runOnV8Thread { isUserLoggedIn = mSession?.isUserSignedIn() ?: false + Log.d(TAG, "signed in " + isUserLoggedIn + " " + mSession) if (isUserLoggedIn) { title = mSession?.loadUserData()?.profile?.name if (title == null) { @@ -270,17 +271,6 @@ class ConvertCSVProvider : DocumentsProvider() { } // END_INCLUDE(query_search_documents) - // BEGIN_INCLUDE(open_document_thumbnail) - @Throws(FileNotFoundException::class) - override fun openDocumentThumbnail(documentId: String, sizeHint: Point, - signal: CancellationSignal): AssetFileDescriptor { - Log.v(TAG, "openDocumentThumbnail") - - val file = getFileForDocId(documentId) - val pfd = ParcelFileDescriptor.open(File("/"), ParcelFileDescriptor.MODE_READ_ONLY) - return AssetFileDescriptor(pfd, 0, AssetFileDescriptor.UNKNOWN_LENGTH) - } - // END_INCLUDE(open_document_thumbnail) // BEGIN_INCLUDE(query_document) @Throws(FileNotFoundException::class) @@ -358,7 +348,7 @@ class ConvertCSVProvider : DocumentsProvider() { return ParcelFileDescriptor.open(outputFile, accessMode, mainHandler) { Log.d(TAG, "closing file " + it?.toString()) - val options = PutFileOptions(encrypt = false) + val options = PutFileOptions() var putFileDone = false val inputStream: InputStream = File(outputFile.path).inputStream() val inputString = inputStream.bufferedReader().use { it.readText() } @@ -383,18 +373,20 @@ class ConvertCSVProvider : DocumentsProvider() { } } } else { - val options = GetFileOptions(decrypt = false) + val options = GetFileOptions() var getFileDone = false - + var fileNotFound = false runOnV8Thread { mSession?.getFile(file.path, options) { + Log.d(TAG, "getFile " + it.value) if (it.hasValue) { - it.value if (it.value is String) { outputFile.writeText(it.value as String) } else { outputFile.writeBytes(it.value as ByteArray) } + } else { + fileNotFound = true } getFileDone = true } @@ -404,6 +396,10 @@ class ConvertCSVProvider : DocumentsProvider() { Thread.sleep(500) } + if (fileNotFound) { + throw FileNotFoundException(file.path) + } + return ParcelFileDescriptor.open(outputFile, accessMode) } } @@ -415,8 +411,7 @@ class ConvertCSVProvider : DocumentsProvider() { override fun createDocument(documentId: String, mimeType: String, displayName: String): String { Log.v(TAG, "createDocument") - val parent = getFileForDocId(documentId) - val file = GaiaFile(parent!!.path + "/" + displayName, false) + val file = GaiaFile(displayName, false) try { // TODO create file } catch (e: IOException) { @@ -527,7 +522,7 @@ class ConvertCSVProvider : DocumentsProvider() { if (mimeType.startsWith("image/")) { // Allow the image to be represented by a thumbnail rather than an icon - flags = flags or Document.FLAG_SUPPORTS_THUMBNAIL + flags = flags // TODO support Document.FLAG_SUPPORTS_THUMBNAIL } val row = result.newRow() @@ -552,12 +547,11 @@ class ConvertCSVProvider : DocumentsProvider() { */ @Throws(FileNotFoundException::class) private fun getFileForDocId(docId: String): GaiaFile? { - var target = mBaseDir if (docId == ROOT) { - return target + return mBaseDir } - target = GaiaFile(docId, false) + val target = GaiaFile(docId, false) return target } diff --git a/app/src/main/java/org/openintents/convertcsv/blockstack/DefaultConfig.kt b/app/src/main/java/org/openintents/convertcsv/blockstack/DefaultConfig.kt index 3d902e9..5355fa3 100644 --- a/app/src/main/java/org/openintents/convertcsv/blockstack/DefaultConfig.kt +++ b/app/src/main/java/org/openintents/convertcsv/blockstack/DefaultConfig.kt @@ -1,7 +1,20 @@ package org.openintents.convertcsv.blockstack +import android.content.Context +import android.content.SharedPreferences +import android.preference.PreferenceManager import org.blockstack.android.sdk.Scope +import org.blockstack.android.sdk.SessionStore import org.blockstack.android.sdk.toBlockstackConfig val defaultConfig = "https://convertcsv.openintents.org".toBlockstackConfig( kotlin.arrayOf(Scope.StoreWrite)) + +private var sessionStore: SessionStore? = null +fun getSessionStore(context:Context):SessionStore { + if (sessionStore == null) { + sessionStore = SessionStore(PreferenceManager.getDefaultSharedPreferences(context)) + } + return sessionStore!! +} + diff --git a/app/src/main/java/org/openintents/convertcsv/common/ConvertCsvBaseActivity.java b/app/src/main/java/org/openintents/convertcsv/common/ConvertCsvBaseActivity.java index 6c5c2d4..b7a4ba3 100644 --- a/app/src/main/java/org/openintents/convertcsv/common/ConvertCsvBaseActivity.java +++ b/app/src/main/java/org/openintents/convertcsv/common/ConvertCsvBaseActivity.java @@ -16,7 +16,6 @@ package org.openintents.convertcsv.common; -import android.app.Activity; import android.app.AlertDialog; import android.app.Dialog; import android.content.ActivityNotFoundException; @@ -25,6 +24,7 @@ import android.content.Intent; import android.content.SharedPreferences; import android.content.SharedPreferences.Editor; +import android.content.pm.PackageManager; import android.database.Cursor; import android.net.Uri; import android.os.Bundle; @@ -33,6 +33,9 @@ import android.os.ParcelFileDescriptor; import android.preference.PreferenceManager; import android.provider.OpenableColumns; +import android.support.v4.content.ContextCompat; +import android.support.v7.app.AppCompatActivity; +import android.text.TextUtils; import android.util.Log; import android.util.Xml.Encoding; import android.view.LayoutInflater; @@ -52,7 +55,6 @@ import org.openintents.convertcsv.PreferenceActivity; import org.openintents.convertcsv.R; import org.openintents.convertcsv.blockstack.AccountActivity; -import org.openintents.distribution.DistributionLibraryActivity; import org.openintents.distribution.DownloadOIAppDialog; import java.io.FileNotFoundException; @@ -62,11 +64,9 @@ import java.io.InputStreamReader; import java.io.OutputStreamWriter; import java.io.Reader; -import java.io.UnsupportedEncodingException; import java.io.Writer; -import java.net.URLDecoder; -public class ConvertCsvBaseActivity extends Activity { +public class ConvertCsvBaseActivity extends AppCompatActivity { static final public int IMPORT_POLICY_DUPLICATE = 0; static final public int IMPORT_POLICY_KEEP = 1; @@ -78,10 +78,12 @@ public class ConvertCsvBaseActivity extends Activity { static final public int MESSAGE_ERROR = 3; // An error occured, arg1 = string ID of error static final public int MESSAGE_SET_MAX_PROGRESS = 4; // Set maximum progress int, arg1 = new max value protected static final int MENU_SETTINGS = Menu.FIRST + 1; + protected static final int MENU_CANCEL = Menu.FIRST + 2; protected static final int MENU_DISTRIBUTION_START = Menu.FIRST + 100; // MUST BE LAST protected static final int DIALOG_ID_WARN_OVERWRITE = 1; protected static final int DIALOG_ID_NO_FILE_MANAGER_AVAILABLE = 2; protected static final int DIALOG_ID_WARN_RESTORE_POLICY = 3; + protected static final int DIALOG_ID_PERMISSIONS = 4; protected static final int DIALOG_DISTRIBUTION_START = 100; // MUST BE LAST protected static final int REQUEST_CODE_PICK_FILE = 1; private final static String TAG = "ConvertCsvBaseActivity"; @@ -93,7 +95,8 @@ public class ConvertCsvBaseActivity extends Activity { static boolean smHasWorkerThread; // Max value for the progress bar. static int smProgressMax; - protected TextView mEditText; + protected TextView mFilePathView; + protected TextView mFileNameView; protected TextView mConvertInfo; protected Spinner mSpinner; protected String PREFERENCE_FILENAME; @@ -192,7 +195,6 @@ public void onCreate(Bundle savedInstanceState) { // Always create the main layout first, since we need to populate the // variables with all the views. switchToMainLayout(); - smHasWorkerThread = false; if (smHasWorkerThread) { switchToConvertLayout(); } @@ -206,15 +208,17 @@ private void switchToMainLayout() { setPreferencesUsed(); - mEditText = findViewById(R.id.file_path); + mFilePathView = findViewById(R.id.file_path); + mFileNameView = findViewById(R.id.file_name); SharedPreferences pm = PreferenceManager.getDefaultSharedPreferences(this); String filepath = pm.getString(PREFERENCE_FILENAME, DEFAULT_FILENAME); - if (filepath.equals(DEFAULT_FILENAME)) { - // prepend SD path - filepath = getSdCardFilename(DEFAULT_FILENAME); + + if (TextUtils.isEmpty(filepath)) { + setFileUriUnknown(); + } else { + setFileUri(Uri.parse(filepath)); } - mEditText.setText(filepath); mBlockstackButton = findViewById(R.id.blockstackButton); @@ -278,12 +282,11 @@ private void switchToMainLayout() { if (type != null && type.equals("text/csv")) { // Someone wants to import a CSV document through the file manager. // Set the path accordingly: - String path = getIntent().getDataString(); + Uri path = getIntent().getData(); if (path != null) { - if (path.startsWith("file://")) { - path = path.substring(7); - } - mEditText.setText(path); + setFileUri(path); + } else { + setFileUriUnknown(); } } } @@ -372,6 +375,11 @@ public String getDefaultImportPolicy() { } public void startImport() { + if (!hasWritePermission()) { + showDialog(DIALOG_ID_PERMISSIONS); + return; + } + int importPolicy = getValidatedImportPolicy(); if (importPolicy == IMPORT_POLICY_RESTORE) { @@ -381,6 +389,15 @@ public void startImport() { } } + private boolean hasWritePermission() { + return ContextCompat.checkSelfPermission(this, getWritePermission()) + == PackageManager.PERMISSION_GRANTED; + } + + protected String getWritePermission() { + return null; + } + public void startImportPostCheck() { // First delete old lists //getContentResolver().delete(Shopping.Contains.CONTENT_URI, null, null); @@ -399,6 +416,7 @@ public void startImportPostCheck() { // what kind of trouble he's getting himself into. switchToConvertLayout(); smHasWorkerThread = true; + supportInvalidateOptionsMenu(); new Thread() { public void run() { @@ -439,27 +457,19 @@ public void run() { } smHasWorkerThread = false; + supportInvalidateOptionsMenu(); } }.start(); } public int getDocumentSize(Uri uri) { - - // The query, since it only applies to a single document, will only return - // one row. There's no need to filter, sort, or select fields, since we want - // all fields for one document. Cursor cursor = getContentResolver() .query(uri, null, null, null, null, null); int size = -1; try { - // moveToFirst() returns false if the cursor has 0 rows. Very handy for - // "if there's anything to look at, look at it" conditionals. if (cursor != null && cursor.moveToFirst()) { - - // Note it's called "Display Name". This is - // provider-specific, and might not necessarily be the file name. String displayName = cursor.getString( cursor.getColumnIndex(OpenableColumns.DISPLAY_NAME)); Log.i(TAG, "Display Name: " + displayName); @@ -477,6 +487,24 @@ public int getDocumentSize(Uri uri) { return size; } + public String getDocumentName(Uri uri) { + Cursor cursor = getContentResolver() + .query(uri, null, null, null, null, null); + + String displayName = uri.getLastPathSegment(); + try { + if (cursor != null && cursor.moveToFirst()) { + displayName = cursor.getString( + cursor.getColumnIndex(OpenableColumns.DISPLAY_NAME)); + } + } finally { + if (cursor != null) { + cursor.close(); + } + } + return displayName; + } + protected Encoding getCurrentEncoding() { if (mCustomEncoding.isChecked()) { return (Encoding) mSpinnerEncoding.getSelectedItem(); @@ -577,7 +605,7 @@ public void doExport(Writer writer) throws IOException { */ public String getFilenameAndSavePreferences() { - String fileName = mEditText.getText().toString(); + String fileName = mFilePathView.getText().toString(); SharedPreferences prefs = PreferenceManager .getDefaultSharedPreferences(this); @@ -609,6 +637,9 @@ public boolean onCreateOptionsMenu(Menu menu) { if (!smHasWorkerThread) { menu.add(0, MENU_SETTINGS, 0, R.string.menu_settings).setShortcut( '1', 's').setIcon(android.R.drawable.ic_menu_preferences); + } else { + menu.add(0, MENU_CANCEL, 0, R.string.menu_cancel).setShortcut( + '1', 'c').setIcon(android.R.drawable.ic_menu_close_clear_cancel); } return true; @@ -627,6 +658,11 @@ public boolean onOptionsItemSelected(MenuItem item) { case MENU_SETTINGS: Intent intent = new Intent(this, PreferenceActivity.class); startActivity(intent); + break; + case MENU_CANCEL: + smHasWorkerThread = false; + finish(); + break; } return super.onOptionsItemSelected(item); } @@ -678,6 +714,14 @@ public void onClick(DialogInterface dialog, int which) { case DIALOG_ID_NO_FILE_MANAGER_AVAILABLE: return new DownloadOIAppDialog(this, DownloadOIAppDialog.OI_FILEMANAGER); + case DIALOG_ID_PERMISSIONS: + return new AlertDialog.Builder(this) + .setTitle(R.string.warn_install_order_title) + .setMessage(R.string.warn_install_order) + .setPositiveButton(android.R.string.ok, (dialog, which) -> { + dialog.dismiss(); + }) + .create(); } return super.onCreateDialog(id); } @@ -698,12 +742,10 @@ private void saveBooleanPreference(String preference, boolean value) { private void openFileManagerForNewDocument() { - String fileName = mEditText.getText().toString(); + String fileName = mFileNameView.getText().toString(); Intent intent = new Intent(Intent.ACTION_CREATE_DOCUMENT); - intent.addCategory(Intent.CATEGORY_OPENABLE); - intent.setType("text/*"); intent.putExtra(Intent.EXTRA_TITLE, fileName); @@ -716,7 +758,7 @@ private void openFileManagerForNewDocument() { private void openFileManagerForChoosingDocument() { - String fileName = mEditText.getText().toString(); + String fileName = mFilePathView.getText().toString(); Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT); @@ -759,25 +801,25 @@ protected void onActivityResult(int requestCode, int resultCode, Intent data) { switch (requestCode) { case REQUEST_CODE_PICK_FILE: if (resultCode == RESULT_OK && data != null) { - // obtain the filename - String filename = data.getDataString(); - // remove url encoding from filename - try { - filename = URLDecoder.decode(filename, "UTF-8"); - } catch (UnsupportedEncodingException e) { - e.printStackTrace(); - } - - if (filename != null) { - if (filename.startsWith("file://")) { - filename = filename.substring(7); - } - - mEditText.setText(filename); + Uri documentUri = data.getData(); + if (documentUri != null) { + setFileUri(documentUri); + } else { + setFileUriUnknown(); } } break; } } + + private void setFileUriUnknown() { + mFileNameView.setText(getString(R.string.unknown_document)); + mFilePathView.setText(""); + } + + private void setFileUri(Uri documentUri) { + mFileNameView.setText(getDocumentName(documentUri)); + mFilePathView.setText(documentUri.toString()); + } } diff --git a/app/src/main/java/org/openintents/convertcsv/notepad/ConvertCsvActivity.java b/app/src/main/java/org/openintents/convertcsv/notepad/ConvertCsvActivity.java index 8024bb3..afa924c 100644 --- a/app/src/main/java/org/openintents/convertcsv/notepad/ConvertCsvActivity.java +++ b/app/src/main/java/org/openintents/convertcsv/notepad/ConvertCsvActivity.java @@ -1,4 +1,4 @@ -/* +/* * Copyright (C) 2008 OpenIntents.org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -16,67 +16,74 @@ package org.openintents.convertcsv.notepad; -import java.io.IOException; -import java.io.Reader; -import java.io.Writer; +import android.os.Bundle; import org.openintents.convertcsv.PreferenceActivity; import org.openintents.convertcsv.R; import org.openintents.convertcsv.common.ConvertCsvBaseActivity; import org.openintents.convertcsv.common.WrongFormatException; -import android.os.Bundle; +import java.io.IOException; +import java.io.Reader; +import java.io.Writer; public class ConvertCsvActivity extends ConvertCsvBaseActivity { - - public static final String TAG = "ConvertCsvActivity"; - + + public static final String TAG = "ConvertCsvActivity"; + public void setPreferencesUsed() { - PREFERENCE_FILENAME = PreferenceActivity.PREFS_NOTEPAD_FILENAME; - DEFAULT_FILENAME = getString(R.string.default_notepad_filename); - PREFERENCE_FORMAT = PreferenceActivity.PREFS_NOTEPAD_FORMAT; - DEFAULT_FORMAT = ImportCsv.FORMAT_PALM_CSV; - PREFERENCE_ENCODING = PreferenceActivity.PREFS_NOTEPAD_ENCODING; - PREFERENCE_USE_CUSTOM_ENCODING = PreferenceActivity.PREFS_NOTEPAD_USE_CUSTOM_ENCODING; - RES_STRING_FILEMANAGER_TITLE = R.string.filemanager_title_notepad; - RES_ARRAY_CSV_FILE_FORMAT = R.array.notepad_format; - RES_ARRAY_CSV_FILE_FORMAT_VALUE = R.array.notepad_format_value; + PREFERENCE_FILENAME = PreferenceActivity.PREFS_NOTEPAD_FILENAME; + DEFAULT_FILENAME = getString(R.string.default_notepad_filename); + PREFERENCE_FORMAT = PreferenceActivity.PREFS_NOTEPAD_FORMAT; + DEFAULT_FORMAT = ImportCsv.FORMAT_PALM_CSV; + PREFERENCE_ENCODING = PreferenceActivity.PREFS_NOTEPAD_ENCODING; + PREFERENCE_USE_CUSTOM_ENCODING = PreferenceActivity.PREFS_NOTEPAD_USE_CUSTOM_ENCODING; + RES_STRING_FILEMANAGER_TITLE = R.string.filemanager_title_notepad; + RES_ARRAY_CSV_FILE_FORMAT = R.array.notepad_format; + RES_ARRAY_CSV_FILE_FORMAT_VALUE = R.array.notepad_format_value; } - - /** Called when the activity is first created. */ + + /** + * Called when the activity is first created. + */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); - + if (mConvertInfo != null) { - mConvertInfo.setText(R.string.convert_all_notes); + mConvertInfo.setText(R.string.convert_all_notes); } } - + @Override public String getImportPolicyPrefString() { - return "notepad_import_policy"; + return "notepad_import_policy"; + } + + /** + * @param reader + * @throws IOException + */ + public void doImport(Reader reader) throws IOException, + WrongFormatException { + ImportCsv ic = new ImportCsv(this); + ic.importCsv(reader, getFormat(), getValidatedImportPolicy()); } - - /** - * @param reader - * @throws IOException - */ - public void doImport(Reader reader) throws IOException, - WrongFormatException { - ImportCsv ic = new ImportCsv(this); - ic.importCsv(reader, getFormat(), getValidatedImportPolicy()); - } - - /** - * @param writer - * @throws IOException - */ - public void doExport(Writer writer) throws IOException { - ExportCsv ec = new ExportCsv(this); - ec.exportCsv(writer, getFormat()); - } - - - + + /** + * @param writer + * @throws IOException + */ + public void doExport(Writer writer) throws IOException { + ExportCsv ec = new ExportCsv(this); + ec.exportCsv(writer, getFormat()); + } + + + @Override + protected String getWritePermission() { + return "org.openintents.notepad.WRITE_PERMISSION"; + } + + } \ No newline at end of file diff --git a/app/src/main/java/org/openintents/convertcsv/shoppinglist/ConvertCsvActivity.java b/app/src/main/java/org/openintents/convertcsv/shoppinglist/ConvertCsvActivity.java index 1ef8def..5199605 100644 --- a/app/src/main/java/org/openintents/convertcsv/shoppinglist/ConvertCsvActivity.java +++ b/app/src/main/java/org/openintents/convertcsv/shoppinglist/ConvertCsvActivity.java @@ -1,4 +1,4 @@ -/* +/* * Copyright (C) 2008 OpenIntents.org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -27,10 +27,6 @@ import android.widget.AdapterView; import android.widget.AdapterView.OnItemSelectedListener; -import java.io.IOException; -import java.io.Reader; -import java.io.Writer; - import org.openintents.convertcsv.PreferenceActivity; import org.openintents.convertcsv.R; import org.openintents.convertcsv.common.ConvertCsvBaseActivity; @@ -38,83 +34,89 @@ import org.openintents.shopping.library.provider.ShoppingContract; import org.openintents.shopping.library.util.ShoppingUtils; +import java.io.IOException; +import java.io.Reader; +import java.io.Writer; + public class ConvertCsvActivity extends ConvertCsvBaseActivity { - public static final String TAG = "ConvertCsvActivity"; + public static final String TAG = "ConvertCsvActivity"; - final String HANDYSHOPPER_FORMAT = "handyshopper"; + final String HANDYSHOPPER_FORMAT = "handyshopper"; - public void setPreferencesUsed() { - PREFERENCE_FILENAME = PreferenceActivity.PREFS_SHOPPINGLIST_FILENAME; - DEFAULT_FILENAME = getString(R.string.default_shoppinglist_filename); - PREFERENCE_FORMAT = PreferenceActivity.PREFS_SHOPPINGLIST_FORMAT; - DEFAULT_FORMAT = "outlook tasks"; - PREFERENCE_ENCODING = PreferenceActivity.PREFS_SHOPPINGLIST_ENCODING; - PREFERENCE_USE_CUSTOM_ENCODING = PreferenceActivity.PREFS_SHOPPINGLIST_USE_CUSTOM_ENCODING; - RES_STRING_FILEMANAGER_TITLE = R.string.filemanager_title_shoppinglist; - RES_ARRAY_CSV_FILE_FORMAT = R.array.shoppinglist_format; - RES_ARRAY_CSV_FILE_FORMAT_VALUE = R.array.shoppinglist_format_value; - } + public void setPreferencesUsed() { + PREFERENCE_FILENAME = PreferenceActivity.PREFS_SHOPPINGLIST_FILENAME; + DEFAULT_FILENAME = getString(R.string.default_shoppinglist_filename); + PREFERENCE_FORMAT = PreferenceActivity.PREFS_SHOPPINGLIST_FORMAT; + DEFAULT_FORMAT = "outlook tasks"; + PREFERENCE_ENCODING = PreferenceActivity.PREFS_SHOPPINGLIST_ENCODING; + PREFERENCE_USE_CUSTOM_ENCODING = PreferenceActivity.PREFS_SHOPPINGLIST_USE_CUSTOM_ENCODING; + RES_STRING_FILEMANAGER_TITLE = R.string.filemanager_title_shoppinglist; + RES_ARRAY_CSV_FILE_FORMAT = R.array.shoppinglist_format; + RES_ARRAY_CSV_FILE_FORMAT_VALUE = R.array.shoppinglist_format_value; + } - /** Called when the activity is first created. */ - @Override - public void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); + /** + * Called when the activity is first created. + */ + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); if (mConvertInfo != null) { - mConvertInfo.setText(R.string.convert_all_shoppinglists); + mConvertInfo.setText(R.string.convert_all_shoppinglists); } - + if (mSpinner != null) { - mSpinner.setOnItemSelectedListener(new OnItemSelectedListener() { - @Override - public void onItemSelected(AdapterView parentView, View selectedItemView, int position, long id) { - updateInfo(); - } - - @Override - public void onNothingSelected(AdapterView parentView) { - updateInfo(); - } - }); + mSpinner.setOnItemSelectedListener(new OnItemSelectedListener() { + @Override + public void onItemSelected(AdapterView parentView, View selectedItemView, int position, long id) { + updateInfo(); + } + + @Override + public void onNothingSelected(AdapterView parentView) { + updateInfo(); + } + }); } - } + } - public void updateInfo() { + public void updateInfo() { if (mConvertInfo == null) return; - String format = getFormat(); - if (DEFAULT_FORMAT.equals(format)) { - mConvertInfo.setText(R.string.convert_all_shoppinglists); + String format = getFormat(); + if (DEFAULT_FORMAT.equals(format)) { + mConvertInfo.setText(R.string.convert_all_shoppinglists); + } else if (HANDYSHOPPER_FORMAT.equals(format)) { + long listId = getCurrentListId(); + String listname = getListName(listId); + if (listname != null) { + String text = getString(R.string.convert_list, listname); + mConvertInfo.setText(text); + } + + } + } + + /** + * @param reader + * @throws IOException + */ + @Override + public void doImport(Reader reader) throws IOException, + WrongFormatException { + ImportCsv ic = new ImportCsv(this, getValidatedImportPolicy()); + String format = getFormat(); + if (DEFAULT_FORMAT.equals(format)) { + ic.importCsv(reader); } else if (HANDYSHOPPER_FORMAT.equals(format)) { - long listId = getCurrentListId(); - String listname = getListName(listId); - if (listname != null) { - String text = getString(R.string.convert_list, listname); - mConvertInfo.setText(text); - } - + SharedPreferences pm = PreferenceManager.getDefaultSharedPreferences(this); + Boolean importStores = pm.getBoolean("shoppinglist_import_stores", true); + long listId = getCurrentListId(); + ic.importHandyShopperCsv(reader, listId, importStores); } - } - - /** - * @param reader - * @throws IOException - */ - @Override - public void doImport(Reader reader) throws IOException, - WrongFormatException { - ImportCsv ic = new ImportCsv(this, getValidatedImportPolicy()); - String format = getFormat(); - if (DEFAULT_FORMAT.equals(format)) { - ic.importCsv(reader); - } else if (HANDYSHOPPER_FORMAT.equals(format)) { - SharedPreferences pm = PreferenceManager.getDefaultSharedPreferences(this); - Boolean importStores = pm.getBoolean("shoppinglist_import_stores", true); - long listId = getCurrentListId(); - ic.importHandyShopperCsv(reader, listId, importStores); - } - } + } @Override public void onImportFinished() { @@ -125,30 +127,30 @@ public void onImportFinished() { } @Override - protected Encoding getDefaultEncoding() { - long id = mSpinner.getSelectedItemId(); - if (0 == id) { - return Encoding.ISO_8859_1; // Default encoding for "MS Outlook Tasks". - } else if (1 == id) { - return Encoding.UTF_8; // Default encoding for "HandyShopper". - } else { - return super.getDefaultEncoding(); - } - } - - /** - * @param writer - * @throws IOException - */ - @Override - public void doExport(Writer writer) throws IOException { - ExportCsv ec = new ExportCsv(this); - String format = getFormat(); - if (DEFAULT_FORMAT.equals(format)) { - ec.exportCsv(writer); - } else if (HANDYSHOPPER_FORMAT.equals(format)) { - long listId = getCurrentListId(); - ec.exportHandyShopperCsv(writer, listId); + protected Encoding getDefaultEncoding() { + long id = mSpinner.getSelectedItemId(); + if (0 == id) { + return Encoding.ISO_8859_1; // Default encoding for "MS Outlook Tasks". + } else if (1 == id) { + return Encoding.UTF_8; // Default encoding for "HandyShopper". + } else { + return super.getDefaultEncoding(); + } + } + + /** + * @param writer + * @throws IOException + */ + @Override + public void doExport(Writer writer) throws IOException { + ExportCsv ec = new ExportCsv(this); + String format = getFormat(); + if (DEFAULT_FORMAT.equals(format)) { + ec.exportCsv(writer); + } else if (HANDYSHOPPER_FORMAT.equals(format)) { + long listId = getCurrentListId(); + ec.exportHandyShopperCsv(writer, listId); /*runOnUiThread(new Runnable() { @Override public void run() { @@ -156,56 +158,61 @@ public void run() { Toast.LENGTH_LONG).show(); } });*/ - } - } - + } + } + /** * @return The string that identifies the import policy for this importer. * null if this derived activity does not support import policies. */ public String getImportPolicyPrefString() { - return "shoppinglist_import_policy"; + return "shoppinglist_import_policy"; } /** * @return The default import policy */ public String getDefaultImportPolicy() { - return "" + IMPORT_POLICY_KEEP; + return "" + IMPORT_POLICY_KEEP; } - + public long getCurrentListId() { - long listId = -1; - - // Try the URI with which Convert CSV has been called: - Uri uri = getIntent().getData(); - Cursor c = getContentResolver().query(uri, - new String[] {ShoppingContract.Lists._ID}, null, null, null); - if (c != null) { - if (c.moveToFirst()) { - listId = c.getLong(0); - } - c.close(); - } - - // Use default list if URI is not valid. - if (listId < 0) { - listId = ShoppingUtils.getDefaultList(this); - } - return listId; + long listId = -1; + + // Try the URI with which Convert CSV has been called: + Uri uri = getIntent().getData(); + Cursor c = getContentResolver().query(uri, + new String[]{ShoppingContract.Lists._ID}, null, null, null); + if (c != null) { + if (c.moveToFirst()) { + listId = c.getLong(0); + } + c.close(); + } + + // Use default list if URI is not valid. + if (listId < 0) { + listId = ShoppingUtils.getDefaultList(this); + } + return listId; } - + public String getListName(long listId) { - String listname = null; - Uri uri = getIntent().getData(); - Cursor c = getContentResolver().query(uri - , new String[] {ShoppingContract.Lists.NAME}, null, null, null); - if (c != null) { - if (c.moveToFirst()) { - listname = c.getString(0); - } - c.close(); - } - return listname; + String listname = null; + Uri uri = getIntent().getData(); + Cursor c = getContentResolver().query(uri, + new String[]{ShoppingContract.Lists.NAME}, null, null, null); + if (c != null) { + if (c.moveToFirst()) { + listname = c.getString(0); + } + c.close(); + } + return listname; + } + + @Override + protected String getWritePermission() { + return "org.openintents.shoppinglist.WRITE_PERMISSION"; } -} \ No newline at end of file +} diff --git a/app/src/main/res/drawable/ic_launcher_folder.png b/app/src/main/res/drawable/ic_launcher_folder.png deleted file mode 100644 index ed31ba5..0000000 Binary files a/app/src/main/res/drawable/ic_launcher_folder.png and /dev/null differ diff --git a/app/src/main/res/drawable/ic_launcher_folder_new_small.png b/app/src/main/res/drawable/ic_launcher_folder_new_small.png new file mode 100644 index 0000000..aa55d24 Binary files /dev/null and b/app/src/main/res/drawable/ic_launcher_folder_new_small.png differ diff --git a/app/src/main/res/layout/activity_account.xml b/app/src/main/res/layout/activity_account.xml index 9088302..b974489 100644 --- a/app/src/main/res/layout/activity_account.xml +++ b/app/src/main/res/layout/activity_account.xml @@ -8,16 +8,14 @@ + android:layout_height="wrap_content"> + app:layout_scrollFlags="scroll|enterAlways" /> diff --git a/app/src/main/res/layout/content_account.xml b/app/src/main/res/layout/content_account.xml index 76c3db2..805f2b9 100644 --- a/app/src/main/res/layout/content_account.xml +++ b/app/src/main/res/layout/content_account.xml @@ -5,39 +5,40 @@ xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" - tools:context="org.blockstack.android.MainActivity" + android:layout_margin="10dp" + tools:context=".blockstack.AccountActivity" tools:ignore="HardcodedText" - tools:showIn="@layout/activity_main"> + tools:showIn="@layout/activity_account"> -