├── .gitignore ├── HACKING.md ├── LICENSE.txt ├── MobileOrg ├── .gitignore ├── build.gradle ├── libs │ ├── CWAC-MergeAdapter.jar │ ├── CWAC-SackOfViewsAdapter.jar │ ├── apache-mime4j-0.6.jar │ ├── dropbox-android-sdk-1.5.3.jar │ ├── httpmime-4.0.3.jar │ ├── json_simple-1.1.jar │ ├── signpost-commonshttp4-1.2.1.1.jar │ └── signpost-core-1.2.1.1.jar └── src │ └── main │ ├── AndroidManifest.xml │ ├── java │ └── com │ │ └── matburt │ │ └── mobileorg │ │ ├── ActivitySwipeDetector.java │ │ ├── AgendaFragment.java │ │ ├── EditNodeActivity.java │ │ ├── EditNodeFragment.java │ │ ├── ItemViewHolder.java │ │ ├── MultipleItemsViewHolder.java │ │ ├── OrgNodeDetailActivity.java │ │ ├── OrgNodeDetailFragment.java │ │ ├── OrgNodeListActivity.java │ │ ├── OrgNodeViewHolder.java │ │ ├── Style.java │ │ ├── SwipeInterface.java │ │ ├── gui │ │ ├── CertificateConflictActivity.java │ │ ├── ErrorReporter.java │ │ ├── FileDecryptionActivity.java │ │ ├── SearchActivity.java │ │ ├── SynchronizerNotification.java │ │ ├── SynchronizerNotificationCompat.java │ │ ├── outline │ │ │ ├── ConflictResolverActivity.java │ │ │ └── OutlineAdapter.java │ │ ├── theme │ │ │ ├── DefaultTheme.java │ │ │ ├── MonoTheme.java │ │ │ └── WhiteTheme.java │ │ └── wizard │ │ │ ├── DirectoryBrowser.java │ │ │ ├── FolderAdapter.java │ │ │ ├── LocalDirectoryBrowser.java │ │ │ ├── WideLinearLayout.java │ │ │ ├── WizardActivity.java │ │ │ └── wizards │ │ │ ├── DropboxDirectoryBrowser.java │ │ │ ├── DropboxWizard.java │ │ │ ├── SDCardWizard.java │ │ │ ├── SSHWizard.java │ │ │ ├── UbuntuOneDirectoryBrowser.java │ │ │ ├── UbuntuOneWizard.java │ │ │ └── WebDAVWizard.java │ │ ├── orgdata │ │ ├── CalendarEntry.java │ │ ├── MobileOrgApplication.java │ │ ├── OrgContract.java │ │ ├── OrgDatabase.java │ │ ├── OrgFile.java │ │ ├── OrgFileParser.java │ │ ├── OrgNode.java │ │ ├── OrgNodeDate.java │ │ ├── OrgNodeParser.java │ │ ├── OrgNodePayload.java │ │ ├── OrgNodeTimeDate.java │ │ ├── OrgNodeTree.java │ │ ├── OrgProvider.java │ │ └── OrgProviderUtils.java │ │ ├── plugin │ │ ├── BundleScrubber.java │ │ ├── PluginBundleManager.java │ │ └── Synchronize.java │ │ ├── services │ │ └── SyncService.java │ │ ├── settings │ │ ├── DirectoryBrowser.java │ │ ├── SettingsActivity.java │ │ ├── SynchronizerPreferences.java │ │ └── synchronizers │ │ │ ├── SDCardSettingsActivity.java │ │ │ ├── ScpSettingsActivity.java │ │ │ ├── UbuntuOneSettingsActivity.java │ │ │ └── WebDAVSettingsActivity.java │ │ ├── synchronizers │ │ ├── AuthData.java │ │ ├── CredentialsProviderAllowHost.java │ │ ├── DropboxSynchronizer.java │ │ ├── JGitWrapper.java │ │ ├── MergeDialogFragment.java │ │ ├── NullSynchronizer.java │ │ ├── ProgressDialogAsyncTask.java │ │ ├── SDCardSynchronizer.java │ │ ├── SSHSynchronizer.java │ │ ├── SshSessionFactory.java │ │ ├── SyncResult.java │ │ ├── Synchronizer.java │ │ ├── UbuntuOneSynchronizer.java │ │ └── WebDAVSynchronizer.java │ │ └── util │ │ ├── FileUtils.java │ │ ├── MultiMap.java │ │ ├── OrgFileNotFoundException.java │ │ ├── OrgNode2Html.java │ │ ├── OrgNodeNotFoundException.java │ │ ├── OrgUtils.java │ │ ├── PreferenceUtils.java │ │ ├── SelectionBuilder.java │ │ └── TodoDialog.java │ └── res │ ├── drawable-hdpi │ ├── ic_dialog_time.png │ ├── ic_menu_add.png │ ├── ic_menu_add2.png │ ├── ic_menu_agenda.png │ ├── ic_menu_archive.png │ ├── ic_menu_close_clear_cancel.png │ ├── ic_menu_delete.png │ ├── ic_menu_directions.png │ ├── ic_menu_edit.png │ ├── ic_menu_help.png │ ├── ic_menu_home.png │ ├── ic_menu_month.png │ ├── ic_menu_moreoverflow.png │ ├── ic_menu_preferences.png │ ├── ic_menu_recent_history.png │ ├── ic_menu_refresh.png │ ├── ic_menu_save.png │ ├── ic_menu_search.png │ ├── ic_menu_star.png │ ├── ic_menu_tag.png │ ├── ic_menu_today.png │ ├── ic_menu_view.png │ └── widget_capture.png │ ├── drawable │ ├── actionbar_background.xml │ ├── background_selector.xml │ ├── border.xml │ ├── capture_widget_text_bg.xml │ ├── go_next.png │ ├── go_next_gray.png │ ├── go_next_pressed.png │ ├── go_next_selected.png │ ├── go_previous.png │ ├── go_previous_gray.png │ ├── go_previous_pressed.png │ ├── go_previous_selected.png │ ├── icon.png │ ├── logo.png │ ├── outline_item_selected.xml │ ├── timeclock_icon.png │ ├── widgetb.png │ ├── widgetnew9.9.png │ ├── wizard_next_button.xml │ └── wizard_previous_button.xml │ ├── layout-w900dp │ └── orgnode_list.xml │ ├── layout │ ├── activity_conflict_resolver.xml │ ├── activity_edit_node.xml │ ├── activity_orgnode_detail.xml │ ├── activity_orgnode_list.xml │ ├── agenda.xml │ ├── agenda_header.xml │ ├── agenda_recycler_item.xml │ ├── agendas.xml │ ├── androidauth.xml │ ├── certconflict.xml │ ├── days_view_holder.xml │ ├── detail_recycler_item.xml │ ├── edit_node_entry.xml │ ├── edit_spinner_layout.xml │ ├── folder_adapter_row.xml │ ├── node_summary_recycler_fragment.xml │ ├── orgnode_list.xml │ ├── outline.xml │ ├── outline_item.xml │ ├── pluginsyncedit.xml │ ├── search.xml │ ├── search_item_layout.xml │ ├── subnode_layout.xml │ ├── sync_notification.xml │ ├── timeclock_dialog.xml │ ├── timeclock_notification.xml │ ├── view.xml │ ├── widget.xml │ ├── wizard_choose_synchronizer.xml │ ├── wizard_dropbox.xml │ ├── wizard_folder_pick_list.xml │ ├── wizard_navbar.xml │ ├── wizard_navbar_first.xml │ ├── wizard_navbar_last.xml │ ├── wizard_next_button.xml │ ├── wizard_null.xml │ ├── wizard_previous_button.xml │ ├── wizard_previous_button_navbar.xml │ ├── wizard_ssh.xml │ ├── wizard_ubuntuone.xml │ └── wizard_webdav.xml │ ├── menu │ ├── agenda_entry.xml │ ├── detail_menu.xml │ ├── edit.xml │ ├── edit_body.xml │ ├── edit_dates.xml │ ├── edit_node_menu.xml │ ├── edit_tags.xml │ ├── main_context_action_bar.xml │ ├── menu_scrolling.xml │ ├── outline_file.xml │ ├── outline_file_uneditable.xml │ ├── outline_menu.xml │ ├── outline_node.xml │ └── outline_node_uneditable.xml │ ├── mipmap-hdpi │ └── ic_launcher.png │ ├── mipmap-mdpi │ └── ic_launcher.png │ ├── mipmap-xhdpi │ └── ic_launcher.png │ ├── mipmap-xxhdpi │ └── ic_launcher.png │ ├── mipmap-xxxhdpi │ └── ic_launcher.png │ ├── raw │ └── upgrade.txt │ ├── values-de │ └── strings.xml │ ├── values-es │ └── strings.xml │ ├── values-v21 │ └── styles.xml │ ├── values-w820dp │ └── dimens.xml │ ├── values-zh │ └── strings.xml │ ├── values │ ├── arrays.xml │ ├── colors.xml │ ├── dimens.xml │ ├── dropbox.xml │ ├── strings.xml │ └── styles.xml │ └── xml │ ├── dropbox_preferences.xml │ ├── preferences.xml │ ├── scp_preferences.xml │ ├── sdsync_preferences.xml │ ├── searchable.xml │ ├── ubuntuone_preferences.xml │ ├── webdav_preferences.xml │ └── widget_mobileorg.xml ├── README.md ├── build.gradle ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── picturesReadme ├── ChildView.png ├── ChildViewResized.png ├── Expended.png ├── ExpendedResized.png ├── FoldedView.png ├── FoldedViewResized.png ├── Main.png ├── MainResized.png ├── Todos.png └── TodosResized.png ├── project.properties ├── settings.gradle └── src-img ├── credits.txt ├── go-next.svg ├── go-previous.svg ├── icon.psd ├── inkscape_pasted_image_20110901_112511.png ├── normal-mdpi-template.svg ├── org-mode-logo.psd ├── qrcode.png ├── screenshot-main.png ├── screenshot-secondary.png ├── screenshot-settings.png ├── wizard_next_button.svg └── wizard_prev_button.svg /.gitignore: -------------------------------------------------------------------------------- 1 | # Android 2 | gen/ 3 | build/ 4 | local.properties 5 | .gradle/ 6 | # Old Android 7 | bin/ 8 | 9 | # Idea 10 | # According to this 11 | # see http://devnet.jetbrains.com/docs/DOC-1186 12 | # I shouldn't ignore most of this stuff.. but looking at the content 13 | # I see environment stuffs in it. 14 | # And I don't see any particular advantage in having the idea stuff 15 | # in my repo 16 | # it would be helpful for code templates but it's simply not worth 17 | # the effort currently 18 | *.iws 19 | *.iml 20 | *.ipr 21 | .idea 22 | out 23 | 24 | # Eclipse 25 | .project 26 | .classpath 27 | .settings 28 | 29 | # Mac 30 | .DS_Store 31 | 32 | # Generic 33 | *~ 34 | .swp 35 | MobileOrg/src/main/project.properties 36 | 37 | MobileOrg/MobileOrg-release.apk 38 | -------------------------------------------------------------------------------- /HACKING.md: -------------------------------------------------------------------------------- 1 | Setting up the build environment 2 | ================================ 3 | 4 | Prerequisites 5 | ------------- 6 | * Java SDK 7 | * Android SDK tools (SDK and build tools) 8 | * (Optional) Android Studio 9 | 10 | Make sure you have the most recent versions. 11 | 12 | Android Studio Setup 13 | -------------------- 14 | Select "Check out from Version Control" on the welcome page and insert 15 | the url to the git repository. Use default settings and a project 16 | should be checked out and built. Remember to configure the path to the 17 | Android SDK. 18 | 19 | Notes regarding Dropbox 20 | ----------------------- 21 | You will need an API key for the dropbox platform if you want to use 22 | dropbox with your own build. Adding the app key to the Manifest.xml 23 | file and inserting the correct keys into values/dropbox.xml will make 24 | dropbox authentication work. 25 | 26 | 27 | Notes regarding pull requests 28 | ----------------------------- 29 | Make sure that any changes or additions that you make will also build from the 30 | command line. This is a requirement before changes will be accepted into the 31 | mainline branch. 32 | 33 | 34 | Notes regarding debian(-like) amd64 build hosts 35 | ----------------------------------------------- 36 | 37 | You might need to install 32bits version of some libraries. 38 | Depending of your system version, you could install the 'ia32-libs' 39 | package, on a 'multiarch' you will need: 'lib32z1', 'libc6-i386' and 40 | 'lib32stdc++6'. 41 | -------------------------------------------------------------------------------- /MobileOrg/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /MobileOrg/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | apply plugin: 'eclipse' 3 | apply plugin: 'maven' 4 | 5 | android { 6 | compileSdkVersion 24 7 | buildToolsVersion "24.0.0" 8 | 9 | defaultConfig { 10 | applicationId "com.matburt.mobileorg" 11 | minSdkVersion 17 12 | targetSdkVersion 24 13 | versionCode 1 14 | versionName "2.0.2" 15 | } 16 | 17 | useLibrary 'org.apache.http.legacy' 18 | 19 | } 20 | 21 | dependencies { 22 | compile fileTree(dir: 'libs', include: ['*.jar']) 23 | testCompile 'junit:junit:4.12' 24 | compile 'com.jcraft:jsch:0.1.50' 25 | compile 'com.android.support:appcompat-v7:24.0.0' 26 | compile 'com.android.support:support-v4:24.0.0' 27 | compile 'com.android.support:recyclerview-v7:24.0.0' 28 | compile 'com.android.support:design:24.0.0' 29 | compile 'com.android.support:cardview-v7:24.0.0' 30 | compile 'org.eclipse.jgit:org.eclipse.jgit:2.1.0.201209190230-r' 31 | } 32 | -------------------------------------------------------------------------------- /MobileOrg/libs/CWAC-MergeAdapter.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/matburt/mobileorg-android/321062ab3189af8f53059d81176b86f201b86bd9/MobileOrg/libs/CWAC-MergeAdapter.jar -------------------------------------------------------------------------------- /MobileOrg/libs/CWAC-SackOfViewsAdapter.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/matburt/mobileorg-android/321062ab3189af8f53059d81176b86f201b86bd9/MobileOrg/libs/CWAC-SackOfViewsAdapter.jar -------------------------------------------------------------------------------- /MobileOrg/libs/apache-mime4j-0.6.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/matburt/mobileorg-android/321062ab3189af8f53059d81176b86f201b86bd9/MobileOrg/libs/apache-mime4j-0.6.jar -------------------------------------------------------------------------------- /MobileOrg/libs/dropbox-android-sdk-1.5.3.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/matburt/mobileorg-android/321062ab3189af8f53059d81176b86f201b86bd9/MobileOrg/libs/dropbox-android-sdk-1.5.3.jar -------------------------------------------------------------------------------- /MobileOrg/libs/httpmime-4.0.3.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/matburt/mobileorg-android/321062ab3189af8f53059d81176b86f201b86bd9/MobileOrg/libs/httpmime-4.0.3.jar -------------------------------------------------------------------------------- /MobileOrg/libs/json_simple-1.1.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/matburt/mobileorg-android/321062ab3189af8f53059d81176b86f201b86bd9/MobileOrg/libs/json_simple-1.1.jar -------------------------------------------------------------------------------- /MobileOrg/libs/signpost-commonshttp4-1.2.1.1.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/matburt/mobileorg-android/321062ab3189af8f53059d81176b86f201b86bd9/MobileOrg/libs/signpost-commonshttp4-1.2.1.1.jar -------------------------------------------------------------------------------- /MobileOrg/libs/signpost-core-1.2.1.1.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/matburt/mobileorg-android/321062ab3189af8f53059d81176b86f201b86bd9/MobileOrg/libs/signpost-core-1.2.1.1.jar -------------------------------------------------------------------------------- /MobileOrg/src/main/java/com/matburt/mobileorg/ActivitySwipeDetector.java: -------------------------------------------------------------------------------- 1 | package com.matburt.mobileorg; 2 | 3 | import android.util.Log; 4 | import android.view.MotionEvent; 5 | import android.view.View; 6 | 7 | public class ActivitySwipeDetector implements View.OnTouchListener { 8 | 9 | static final String logTag = "ActivitySwipeDetector"; 10 | static final int MIN_DISTANCE = 100; 11 | private SwipeInterface activity; 12 | private float downX, downY, upX, upY; 13 | 14 | public ActivitySwipeDetector(SwipeInterface activity){ 15 | this.activity = activity; 16 | } 17 | 18 | public void onRightToLeftSwipe(View v){ 19 | activity.right2left(v); 20 | } 21 | 22 | public void onLeftToRightSwipe(View v){ 23 | activity.left2right(v); 24 | } 25 | 26 | public boolean onTouch(View v, MotionEvent event) { 27 | switch(event.getAction()){ 28 | case MotionEvent.ACTION_UP: { 29 | upX = event.getX(); 30 | upY = event.getY(); 31 | 32 | float deltaX = downX - upX; 33 | float deltaY = downY - upY; 34 | 35 | // swipe horizontal? 36 | if(Math.abs(deltaX) > MIN_DISTANCE){ 37 | // left or right 38 | if(deltaX < 0) { this.onLeftToRightSwipe(v); return true; } 39 | if(deltaX > 0) { this.onRightToLeftSwipe(v); return true; } 40 | } 41 | else { 42 | } 43 | } 44 | } 45 | return false; 46 | } 47 | } 48 | 49 | -------------------------------------------------------------------------------- /MobileOrg/src/main/java/com/matburt/mobileorg/EditNodeActivity.java: -------------------------------------------------------------------------------- 1 | package com.matburt.mobileorg; 2 | 3 | import android.content.Intent; 4 | import android.os.Bundle; 5 | import android.support.v4.app.NavUtils; 6 | import android.support.v7.app.AppCompatActivity; 7 | import android.support.v7.widget.Toolbar; 8 | import android.view.Menu; 9 | import android.view.MenuInflater; 10 | import android.view.MenuItem; 11 | 12 | /** 13 | * An activity representing a single OrgNode detail screen. This 14 | * activity is only used narrow width devices. On tablet-size devices, 15 | * item details are presented side-by-side with a list of items 16 | * in a {@link OrgNodeListActivity}. 17 | */ 18 | public class EditNodeActivity extends AppCompatActivity { 19 | EditNodeFragment fragment; 20 | public static String EDIT_NODE_FRAGMENT = "edit_node_fragment_tag"; 21 | 22 | @Override 23 | protected void onCreate(Bundle savedInstanceState) { 24 | super.onCreate(savedInstanceState); 25 | setContentView(R.layout.activity_edit_node); 26 | Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar_1); 27 | setSupportActionBar(toolbar); 28 | getSupportActionBar().setTitle(""); 29 | 30 | 31 | // savedInstanceState is non-null when there is fragment state 32 | // saved from previous configurations of this activity 33 | // (e.g. when rotating the screen from portrait to landscape). 34 | // In this case, the fragment will automatically be re-added 35 | // to its container so we don't need to manually add it. 36 | // For more information, see the Fragments API guide at: 37 | // 38 | // http://developer.android.com/guide/components/fragments.html 39 | // 40 | if (savedInstanceState == null) { 41 | // Create the detail fragment and add it to the activity 42 | // using a fragment transaction. 43 | 44 | fragment = new EditNodeFragment(); 45 | fragment.setArguments(getIntent().getExtras()); 46 | getSupportFragmentManager().beginTransaction() 47 | .replace(R.id.edit_node_container, fragment, EDIT_NODE_FRAGMENT) 48 | .commit(); 49 | } 50 | } 51 | 52 | @Override 53 | public boolean onCreateOptionsMenu(Menu menu) { 54 | MenuInflater inflater = getMenuInflater(); 55 | inflater.inflate(R.menu.edit_node_menu, menu); 56 | 57 | return true; 58 | } 59 | 60 | @Override 61 | public boolean onOptionsItemSelected(MenuItem item) { 62 | switch (item.getItemId()) { 63 | case android.R.id.home: 64 | // This ID represents the Home or Up button. In the case of this 65 | // activity, the Up button is shown. Use NavUtils to allow users 66 | // to navigate up one level in the application structure. For 67 | // more details, see the Navigation pattern on Android Design: 68 | // 69 | // http://developer.android.com/design/patterns/navigation.html#up-vs-back 70 | // 71 | NavUtils.navigateUpTo(this, new Intent(this, OrgNodeListActivity.class)); 72 | return true; 73 | 74 | case R.id.edit_menu_ok: 75 | 76 | boolean shouldFinish = ((EditNodeFragment)(getSupportFragmentManager().findFragmentByTag(EDIT_NODE_FRAGMENT))).onOKPressed(); 77 | if(shouldFinish) finish(); 78 | // Intent intent = new Intent(this, OrgNodeListActivity.class); 79 | // startActivity(intent); 80 | return true; 81 | case R.id.edit_menu_cancel: 82 | ((EditNodeFragment)(getSupportFragmentManager().findFragmentByTag(EDIT_NODE_FRAGMENT))).onCancelPressed(); 83 | finish(); 84 | // intent = new Intent(this, OrgNodeListActivity.class); 85 | // startActivity(intent); 86 | return true; 87 | } 88 | // return super.onOptionsItemSelected(item); 89 | return false; 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /MobileOrg/src/main/java/com/matburt/mobileorg/ItemViewHolder.java: -------------------------------------------------------------------------------- 1 | package com.matburt.mobileorg; 2 | 3 | import android.support.v7.widget.RecyclerView; 4 | import android.view.View; 5 | 6 | public class ItemViewHolder extends RecyclerView.ViewHolder { 7 | 8 | public ItemViewHolder(View view) { 9 | super(view); 10 | } 11 | } -------------------------------------------------------------------------------- /MobileOrg/src/main/java/com/matburt/mobileorg/MultipleItemsViewHolder.java: -------------------------------------------------------------------------------- 1 | package com.matburt.mobileorg; 2 | 3 | import android.support.v7.widget.RecyclerView; 4 | import android.view.View; 5 | 6 | public class MultipleItemsViewHolder extends RecyclerView.ViewHolder { 7 | View view; 8 | 9 | public MultipleItemsViewHolder(View view) { 10 | super(view); 11 | this.view = view; 12 | } 13 | 14 | // @Override 15 | // public void onViewRecycled(ItemViewHolder holder) { 16 | // holder.itemView.setOnLongClickListener(null); 17 | // super.onViewRecycled(holder); 18 | // } 19 | 20 | 21 | 22 | // @Override 23 | // public String toString() { 24 | // return super.toString() + " '" + mContentView.getText() + "'"; 25 | // } 26 | 27 | 28 | 29 | } -------------------------------------------------------------------------------- /MobileOrg/src/main/java/com/matburt/mobileorg/Style.java: -------------------------------------------------------------------------------- 1 | package com.matburt.mobileorg; 2 | 3 | import android.content.Context; 4 | import android.support.v4.content.ContextCompat; 5 | 6 | public class Style { 7 | public static int gray, red, green, yellow, blue, foreground, foregroundDark, black, background, highlightedBackground; 8 | public static int nTitleColors = 3; 9 | public static int[] titleColor; 10 | public static int[] titleFontSize; 11 | 12 | Style(Context context){ 13 | gray = ContextCompat.getColor(context, R.color.colorGray); 14 | red = ContextCompat.getColor(context, R.color.colorRed); 15 | green = ContextCompat.getColor(context, R.color.colorGreen); 16 | yellow = ContextCompat.getColor(context, R.color.colorYellow); 17 | blue = ContextCompat.getColor(context, R.color.colorBlue); 18 | foreground = ContextCompat.getColor(context, R.color.colorPrimary); 19 | foregroundDark = ContextCompat.getColor(context, R.color.colorPrimaryDark); 20 | black = ContextCompat.getColor(context, R.color.colorBlack); 21 | 22 | titleColor = new int[nTitleColors]; 23 | titleColor[0] = foregroundDark; 24 | titleColor[1] = foreground; 25 | titleColor[2] = black; 26 | 27 | titleFontSize = new int[nTitleColors]; 28 | titleFontSize[0] = 25; 29 | titleFontSize[1] = 20; 30 | titleFontSize[2] = 16; 31 | } 32 | 33 | } 34 | -------------------------------------------------------------------------------- /MobileOrg/src/main/java/com/matburt/mobileorg/SwipeInterface.java: -------------------------------------------------------------------------------- 1 | package com.matburt.mobileorg; 2 | 3 | import android.view.View; 4 | 5 | public interface SwipeInterface { 6 | 7 | void left2right(View v); 8 | 9 | void right2left(View v); 10 | 11 | } 12 | -------------------------------------------------------------------------------- /MobileOrg/src/main/java/com/matburt/mobileorg/gui/CertificateConflictActivity.java: -------------------------------------------------------------------------------- 1 | package com.matburt.mobileorg.gui; 2 | 3 | import android.app.Activity; 4 | import android.content.SharedPreferences; 5 | import android.content.SharedPreferences.Editor; 6 | import android.os.Bundle; 7 | import android.preference.PreferenceManager; 8 | import android.view.View; 9 | import android.widget.Button; 10 | import android.widget.TextView; 11 | 12 | import com.matburt.mobileorg.R; 13 | 14 | public class CertificateConflictActivity extends Activity { 15 | 16 | private TextView hash_details; 17 | private TextView cert_descr; 18 | private Button accept_button; 19 | private Button deny_button; 20 | private View.OnClickListener acceptListener = new View.OnClickListener() { 21 | public void onClick(View v) { 22 | accept(); 23 | finish(); 24 | } 25 | }; 26 | private View.OnClickListener denyListener = new View.OnClickListener() { 27 | public void onClick(View v) { 28 | finish(); 29 | } 30 | }; 31 | 32 | public void onCreate(Bundle savedInstanceState) { 33 | // OrgUtils.setTheme(this); 34 | super.onCreate(savedInstanceState); 35 | setContentView(R.layout.certconflict); 36 | 37 | this.hash_details = (TextView) this.findViewById(R.id.cert_hash_details); 38 | this.cert_descr = (TextView) this.findViewById(R.id.cert_new_descr); 39 | this.accept_button = (Button) this.findViewById(R.id.cert_conflict_accept); 40 | this.accept_button.setOnClickListener(acceptListener); 41 | this.deny_button = (Button) this.findViewById(R.id.cert_conflict_deny); 42 | this.deny_button.setOnClickListener(denyListener); 43 | 44 | SharedPreferences appSettings = 45 | PreferenceManager.getDefaultSharedPreferences(this); 46 | String webCertHash = Integer.toString(appSettings.getInt("webCertHash", 0)); 47 | String conflictHash = Integer.toString(appSettings.getInt("webConflictHash", 0)); 48 | String conflictDetails = appSettings.getString("webConflictHashDesc", ""); 49 | this.hash_details.setText("Previous Hash: " + webCertHash + " does not match the current one: " + conflictHash); 50 | this.cert_descr.setText("The New Certificate Looks like this:\n" + conflictDetails); 51 | } 52 | 53 | private void accept() { 54 | SharedPreferences appSettings = 55 | PreferenceManager.getDefaultSharedPreferences(this); 56 | Editor edit = appSettings.edit(); 57 | edit.putInt("webCertHash", appSettings.getInt("webConflictHash", 0)); 58 | edit.putString("webCertDesscr", appSettings.getString("webConflictHashDesc", "")); 59 | edit.commit(); 60 | } 61 | } -------------------------------------------------------------------------------- /MobileOrg/src/main/java/com/matburt/mobileorg/gui/ErrorReporter.java: -------------------------------------------------------------------------------- 1 | package com.matburt.mobileorg.gui; 2 | 3 | import android.app.AlertDialog; 4 | import android.content.Context; 5 | 6 | import com.matburt.mobileorg.R; 7 | 8 | public class ErrorReporter 9 | { 10 | private static final String LT = "MobileOrg"; 11 | 12 | public static void displayError(Context context, String message) { 13 | AlertDialog.Builder dialog = new AlertDialog.Builder(context); 14 | dialog.setTitle(R.string.error_dialog_title); 15 | dialog.setMessage(message); 16 | dialog.setNeutralButton("Ok", null); 17 | dialog.create().show(); 18 | } 19 | 20 | public static void displayError(Context context, Exception e) { 21 | // Log.e(LT, e.toString()); 22 | ErrorReporter.displayError(context, e.getMessage()); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /MobileOrg/src/main/java/com/matburt/mobileorg/gui/FileDecryptionActivity.java: -------------------------------------------------------------------------------- 1 | package com.matburt.mobileorg.gui; 2 | 3 | import android.app.Activity; 4 | import android.content.ActivityNotFoundException; 5 | import android.content.Intent; 6 | import android.content.pm.PackageInfo; 7 | import android.content.pm.PackageManager.NameNotFoundException; 8 | import android.os.Bundle; 9 | import android.widget.Toast; 10 | 11 | import com.matburt.mobileorg.orgdata.OrgDatabase; 12 | import com.matburt.mobileorg.orgdata.OrgFile; 13 | import com.matburt.mobileorg.orgdata.OrgFileParser; 14 | import com.matburt.mobileorg.R; 15 | 16 | import java.io.BufferedReader; 17 | import java.io.ByteArrayInputStream; 18 | import java.io.InputStreamReader; 19 | 20 | public class FileDecryptionActivity extends Activity 21 | { 22 | private static final String mApgPackageName = "org.thialfihar.android.apg"; 23 | private static final int mMinRequiredVersion = 16; 24 | private static final String DECRYPT_AND_RETURN = "org.thialfihar.android.apg.intent.DECRYPT_AND_RETURN"; 25 | private static final int DECRYPT_MESSAGE = 0x21070001; 26 | private static final String EXTRA_DATA = "data"; 27 | private static final String EXTRA_DECRYPTED_MESSAGE = "decryptedMessage"; 28 | 29 | private String filename; 30 | private String name; 31 | private String checksum; 32 | 33 | @Override 34 | public void onCreate(Bundle savedInstanceState) { 35 | super.onCreate(savedInstanceState); 36 | 37 | if(isAvailable() == false) 38 | return; 39 | 40 | Intent intent = getIntent(); 41 | 42 | this.filename = intent.getStringExtra("filename"); 43 | this.name = intent.getStringExtra("filenameAlias"); 44 | this.checksum = intent.getStringExtra("checksum"); 45 | byte[] data = intent.getByteArrayExtra("data"); 46 | 47 | if (data == null) 48 | return; 49 | 50 | Intent APGintent = new Intent(DECRYPT_AND_RETURN); 51 | APGintent.setType("text/plain"); 52 | APGintent.putExtra(FileDecryptionActivity.EXTRA_DATA, data); 53 | 54 | try { 55 | startActivityForResult(APGintent, DECRYPT_MESSAGE); 56 | } catch (ActivityNotFoundException e) { 57 | // Log.e("MobileOrg", "Error: " + e.getMessage() + " while launching APG intent"); 58 | } 59 | } 60 | 61 | @Override 62 | public void onActivityResult(int requestCode, int resultCode, Intent intent) { 63 | switch (requestCode) { 64 | case FileDecryptionActivity.DECRYPT_MESSAGE: 65 | if (resultCode != RESULT_OK || intent == null) 66 | return; 67 | 68 | String decryptedData = intent 69 | .getStringExtra(FileDecryptionActivity.EXTRA_DECRYPTED_MESSAGE); 70 | BufferedReader reader = new BufferedReader(new InputStreamReader( 71 | new ByteArrayInputStream(decryptedData.getBytes()))); 72 | 73 | OrgDatabase db = OrgDatabase.getInstance(); 74 | OrgFileParser.getInstance().parse(new OrgFile(filename, name), reader, this); 75 | break; 76 | } 77 | finish(); 78 | } 79 | 80 | private boolean isAvailable() { 81 | try { 82 | PackageInfo pi = getPackageManager().getPackageInfo( 83 | mApgPackageName, 0); 84 | if (pi.versionCode >= mMinRequiredVersion) { 85 | return true; 86 | } else { 87 | Toast.makeText(this, R.string.error_apg_version_not_supported, 88 | Toast.LENGTH_SHORT).show(); 89 | } 90 | } catch (NameNotFoundException e) { 91 | Toast.makeText(this, R.string.error_apg_not_found, Toast.LENGTH_SHORT) 92 | .show(); 93 | } 94 | return false; 95 | } 96 | } -------------------------------------------------------------------------------- /MobileOrg/src/main/java/com/matburt/mobileorg/gui/SynchronizerNotification.java: -------------------------------------------------------------------------------- 1 | package com.matburt.mobileorg.gui; 2 | 3 | import android.annotation.TargetApi; 4 | import android.app.Notification; 5 | import android.app.NotificationManager; 6 | import android.app.PendingIntent; 7 | import android.content.Context; 8 | import android.content.Intent; 9 | import android.os.Build; 10 | 11 | import com.matburt.mobileorg.OrgNodeListActivity; 12 | import com.matburt.mobileorg.R; 13 | 14 | @TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH) 15 | public class SynchronizerNotification extends SynchronizerNotificationCompat { 16 | private NotificationManager notificationManager; 17 | private Notification notification; 18 | private int notifyRef = 1; 19 | private Context context; 20 | 21 | public SynchronizerNotification(Context context) { 22 | super(context); 23 | this.context = context; 24 | } 25 | 26 | @Override 27 | public void errorNotification(String errorMsg) { 28 | this.notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE); 29 | Intent notifyIntent = new Intent(context, OrgNodeListActivity.class); 30 | notifyIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP 31 | | Intent.FLAG_ACTIVITY_SINGLE_TOP); 32 | notifyIntent.putExtra("ERROR_MESSAGE", errorMsg); 33 | notifyIntent.setAction("com.matburt.mobileorg.SYNC_FAILED"); 34 | 35 | PendingIntent contentIntent = PendingIntent.getActivity(context, 0, notifyIntent, 0); 36 | 37 | Notification.Builder builder = new Notification.Builder(context); 38 | builder.setContentIntent(contentIntent); 39 | builder.setSmallIcon(R.drawable.icon); 40 | builder.setContentTitle(context.getString(R.string.sync_failed)); 41 | builder.setContentText(errorMsg); 42 | notification = builder.getNotification(); 43 | notification.flags = Notification.FLAG_AUTO_CANCEL; 44 | 45 | notificationManager.notify(notifyRef, notification); 46 | } 47 | 48 | 49 | @Override 50 | @SuppressWarnings("deprecation") 51 | public void setupNotification() { 52 | this.notificationManager = (NotificationManager) context 53 | .getSystemService(Context.NOTIFICATION_SERVICE); 54 | Intent notifyIntent = new Intent(context, OrgNodeListActivity.class); 55 | notifyIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP 56 | | Intent.FLAG_ACTIVITY_SINGLE_TOP); 57 | 58 | PendingIntent contentIntent = PendingIntent.getActivity(context, 0, 59 | notifyIntent, 0); 60 | 61 | Notification.Builder builder = new Notification.Builder(context); 62 | builder.setContentIntent(contentIntent); 63 | builder.setSmallIcon(R.drawable.icon); 64 | builder.setOngoing(true); 65 | builder.setContentTitle(context.getString(R.string.sync_synchronizing_changes)); 66 | builder.setProgress(100, 0, true); 67 | notification = builder.getNotification(); 68 | 69 | notificationManager.notify(notifyRef, notification); 70 | } 71 | 72 | @Override 73 | public void updateNotification(String message) { 74 | if(notification == null) 75 | return; 76 | 77 | if(message != null) { 78 | notificationManager.notify(notifyRef, notification); 79 | } 80 | } 81 | 82 | @Override 83 | public void updateNotification(int progress) { 84 | updateNotification(progress, null); 85 | } 86 | 87 | @Override 88 | public void updateNotification(int progress, String message) { 89 | if(notification == null) 90 | return; 91 | 92 | // FIXME: 93 | // This was commented because contentView is null on Android Nougat 94 | // But we must find a way to make it work 95 | // notification.contentView.setProgressBar(android.R.id.progress, 100, 96 | // progress, false); 97 | 98 | notificationManager.notify(notifyRef, notification); 99 | } 100 | 101 | @Override 102 | public void finalizeNotification() { 103 | notificationManager.cancel(notifyRef); 104 | } 105 | 106 | } 107 | -------------------------------------------------------------------------------- /MobileOrg/src/main/java/com/matburt/mobileorg/gui/SynchronizerNotificationCompat.java: -------------------------------------------------------------------------------- 1 | package com.matburt.mobileorg.gui; 2 | 3 | import android.app.Notification; 4 | import android.app.NotificationManager; 5 | import android.app.PendingIntent; 6 | import android.content.Context; 7 | import android.content.Intent; 8 | import android.support.v4.app.NotificationCompat; 9 | import android.support.v4.app.NotificationCompat.Builder; 10 | import android.widget.RemoteViews; 11 | 12 | import com.matburt.mobileorg.OrgNodeListActivity; 13 | import com.matburt.mobileorg.R; 14 | 15 | public class SynchronizerNotificationCompat { 16 | private NotificationManager notificationManager; 17 | private Notification notification; 18 | private int notifyRef = 1; 19 | private Context context; 20 | 21 | public SynchronizerNotificationCompat(Context context) { 22 | this.context = context; 23 | } 24 | 25 | public void errorNotification(String errorMsg) { 26 | this.notificationManager = (NotificationManager) context 27 | .getSystemService(Context.NOTIFICATION_SERVICE); 28 | Intent notifyIntent = new Intent(context, OrgNodeListActivity.class); 29 | notifyIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP 30 | | Intent.FLAG_ACTIVITY_SINGLE_TOP); 31 | 32 | PendingIntent contentIntent = PendingIntent.getActivity(context, 0, 33 | notifyIntent, 0); 34 | 35 | Builder builder = new NotificationCompat.Builder(context); 36 | builder.setContentIntent(contentIntent); 37 | builder.setSmallIcon(R.drawable.icon); 38 | builder.setContentTitle("Synchronization failed"); 39 | 40 | notification = builder.getNotification(); 41 | notification.contentView = notification.contentView = new RemoteViews( 42 | context.getPackageName(), R.layout.sync_notification); 43 | 44 | notification.contentView.setImageViewResource(R.id.status_icon, 45 | R.drawable.icon); 46 | notification.contentView.setTextViewText(R.id.status_text, errorMsg); 47 | notification.contentView.setProgressBar(R.id.status_progress, 100, 100, 48 | false); 49 | notificationManager.notify(notifyRef, notification); 50 | } 51 | 52 | public void setupNotification() { 53 | this.notificationManager = (NotificationManager) context 54 | .getSystemService(Context.NOTIFICATION_SERVICE); 55 | Intent notifyIntent = new Intent(context, OrgNodeListActivity.class); 56 | notifyIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP 57 | | Intent.FLAG_ACTIVITY_SINGLE_TOP); 58 | 59 | PendingIntent contentIntent = PendingIntent.getActivity(context, 0, 60 | notifyIntent, 0); 61 | 62 | Builder builder = new NotificationCompat.Builder(context); 63 | builder.setContentIntent(contentIntent); 64 | builder.setSmallIcon(R.drawable.icon); 65 | builder.setOngoing(true); 66 | builder.setContentTitle("Started synchronization"); 67 | builder.setContentText("Started synchronization"); 68 | notification = builder.getNotification(); 69 | 70 | notification.contentView = new RemoteViews(context.getPackageName(), 71 | R.layout.sync_notification); 72 | 73 | notification.contentView.setImageViewResource(R.id.status_icon, 74 | R.drawable.icon); 75 | notification.contentView.setTextViewText(R.id.status_text, 76 | context.getString(R.string.sync_synchronizing_changes)); 77 | notification.contentView.setProgressBar(R.id.status_progress, 100, 0, 78 | true); 79 | 80 | notificationManager.notify(notifyRef, notification); 81 | } 82 | 83 | public void updateNotification(String message) { 84 | if(notification == null) 85 | return; 86 | 87 | if(message != null) { 88 | notification.contentView.setTextViewText(R.id.status_text, message); 89 | notificationManager.notify(notifyRef, notification); 90 | } 91 | } 92 | 93 | public void updateNotification(int progress) { 94 | updateNotification(progress, null); 95 | } 96 | 97 | public void updateNotification(int progress, String message) { 98 | if(notification == null) 99 | return; 100 | 101 | if(message != null) 102 | notification.contentView.setTextViewText(R.id.status_text, message); 103 | 104 | notification.contentView.setProgressBar(R.id.status_progress, 100, 105 | progress, false); 106 | notificationManager.notify(notifyRef, notification); 107 | } 108 | 109 | public void finalizeNotification() { 110 | notificationManager.cancel(notifyRef); 111 | } 112 | 113 | } 114 | -------------------------------------------------------------------------------- /MobileOrg/src/main/java/com/matburt/mobileorg/gui/outline/ConflictResolverActivity.java: -------------------------------------------------------------------------------- 1 | package com.matburt.mobileorg.gui.outline; 2 | 3 | import android.content.ContentValues; 4 | import android.content.Intent; 5 | import android.os.Bundle; 6 | import android.support.v4.app.NavUtils; 7 | import android.support.v7.app.ActionBar; 8 | import android.support.v7.app.AppCompatActivity; 9 | import android.support.v7.widget.Toolbar; 10 | import android.view.Menu; 11 | import android.view.MenuInflater; 12 | import android.view.MenuItem; 13 | import android.widget.EditText; 14 | 15 | import com.matburt.mobileorg.orgdata.OrgContract; 16 | import com.matburt.mobileorg.orgdata.OrgFile; 17 | import com.matburt.mobileorg.OrgNodeListActivity; 18 | import com.matburt.mobileorg.R; 19 | import com.matburt.mobileorg.synchronizers.JGitWrapper; 20 | import com.matburt.mobileorg.synchronizers.Synchronizer; 21 | import com.matburt.mobileorg.util.OrgFileNotFoundException; 22 | import com.matburt.mobileorg.util.OrgUtils; 23 | 24 | public class ConflictResolverActivity extends AppCompatActivity { 25 | 26 | EditText editText; 27 | String filename; 28 | Long nodeId; 29 | 30 | @Override 31 | protected void onCreate(Bundle savedInstanceState) { 32 | super.onCreate(savedInstanceState); 33 | setContentView(R.layout.activity_conflict_resolver); 34 | Toolbar toolbar = (Toolbar) findViewById(R.id.detail_toolbar); 35 | setSupportActionBar(toolbar); 36 | 37 | // Show the Up button in the action bar. 38 | ActionBar actionBar = getSupportActionBar(); 39 | 40 | 41 | 42 | if (savedInstanceState == null) { 43 | // Create the detail fragment and add it to the activity 44 | // using a fragment transaction. 45 | Bundle arguments = new Bundle(); 46 | nodeId = getIntent().getLongExtra(OrgContract.NODE_ID, -1); 47 | 48 | editText = (EditText)findViewById(R.id.conflict_resolver_text); 49 | try { 50 | OrgFile file = new OrgFile(nodeId, getContentResolver()); 51 | if (actionBar != null) { 52 | actionBar.setTitle(file.name); 53 | } 54 | 55 | String dir = Synchronizer.getInstance().getAbsoluteFilesDir(this); 56 | this.filename = dir+"/"+file.filename; 57 | editText.setText(OrgUtils.readAll(this.filename)); 58 | 59 | } catch (OrgFileNotFoundException e) { 60 | e.printStackTrace(); 61 | } 62 | } 63 | } 64 | 65 | @Override 66 | public boolean onCreateOptionsMenu(Menu menu) { 67 | MenuInflater inflater = getMenuInflater(); 68 | inflater.inflate(R.menu.edit_node_menu, menu); 69 | 70 | return true; 71 | } 72 | 73 | @Override 74 | public boolean onOptionsItemSelected(MenuItem item) { 75 | switch (item.getItemId()) { 76 | case R.id.edit_menu_cancel: 77 | NavUtils.navigateUpTo(this, new Intent(this, OrgNodeListActivity.class)); 78 | return true; 79 | case R.id.edit_menu_ok: 80 | if(this.filename!=null && !this.filename.equals("")){ 81 | OrgUtils.writeToFile(this.filename, editText.getText().toString()); 82 | new JGitWrapper.MergeTask(this, this.filename).execute(); 83 | OrgFile f = null; 84 | try { 85 | f = new OrgFile(nodeId, this.getContentResolver()); 86 | ContentValues values = new ContentValues(); 87 | values.put("comment", ""); 88 | f.updateFileInDB(this.getContentResolver(), values); 89 | } catch (OrgFileNotFoundException e) { 90 | e.printStackTrace(); 91 | } 92 | 93 | } 94 | NavUtils.navigateUpTo(this, new Intent(this, OrgNodeListActivity.class)); 95 | return true; 96 | } 97 | return false; 98 | } 99 | 100 | 101 | } 102 | -------------------------------------------------------------------------------- /MobileOrg/src/main/java/com/matburt/mobileorg/gui/theme/DefaultTheme.java: -------------------------------------------------------------------------------- 1 | package com.matburt.mobileorg.gui.theme; 2 | 3 | import android.content.Context; 4 | import android.graphics.Color; 5 | 6 | import com.matburt.mobileorg.util.PreferenceUtils; 7 | 8 | public class DefaultTheme { 9 | 10 | public int gray = Color.GRAY; 11 | 12 | public int c0Black = Color.rgb(0x00, 0x00, 0x00); 13 | public int c1Red = Color.rgb(0xd0, 0x00, 0x00); 14 | public int c2Green = Color.rgb(0x00, 0xa0, 0x00); 15 | public int c3Yellow = Color.rgb(0xc0, 0x80, 0x00); 16 | public int c4Blue = Color.rgb(0x22, 0x22, 0xf0); 17 | public int c5Purple = Color.rgb(0xa0, 0x00, 0xa0); 18 | public int c6Cyan = Color.rgb(0x00, 0x80, 0x80); 19 | public int c7White = Color.rgb(0xc0, 0xc0, 0xc0); 20 | 21 | public int c9LRed = Color.rgb(0xff, 0x77, 0x77); 22 | public int caLGreen = Color.rgb(0x77, 0xff, 0x77); 23 | public int cbLYellow = Color.rgb(0xff, 0xff, 0x00); 24 | public int ccLBlue = Color.rgb(0x88, 0x88, 0xff); 25 | public int cdLPurple = Color.rgb(0xff, 0x00, 0xff); 26 | public int ceLCyan = Color.rgb(0x00, 0xff, 0xff); 27 | public int cfLWhite = Color.rgb(0xff, 0xff, 0xff); 28 | 29 | public int defaultForeground = Color.rgb(0xc0, 0xc0, 0xc0); 30 | public int defaultBackground = Color.rgb(0x00, 0x00, 0x00); 31 | 32 | public int[] levelColors; 33 | 34 | public String defaultFontColor = "white"; 35 | 36 | public DefaultTheme() { 37 | levelColors = new int[] { ccLBlue, c3Yellow, ceLCyan, c2Green, 38 | c5Purple, ccLBlue, c2Green, ccLBlue, c3Yellow, ceLCyan }; 39 | } 40 | 41 | 42 | public static DefaultTheme getTheme(Context context) { 43 | final String themeName = PreferenceUtils.getThemeName(); 44 | if(themeName.equals("Light")) 45 | return new WhiteTheme(); 46 | else if(themeName.equals("Monochrome")) 47 | return new MonoTheme(); 48 | else 49 | return new DefaultTheme(); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /MobileOrg/src/main/java/com/matburt/mobileorg/gui/theme/MonoTheme.java: -------------------------------------------------------------------------------- 1 | package com.matburt.mobileorg.gui.theme; 2 | 3 | import android.graphics.Color; 4 | 5 | public class MonoTheme extends DefaultTheme { 6 | 7 | public MonoTheme() { 8 | super(); 9 | c0Black = Color.rgb(0xff, 0xff, 0xff); 10 | c1Red = Color.rgb(0xd0, 0x00, 0x00); 11 | c2Green = Color.rgb(0x00, 0x00, 0x00); 12 | c3Yellow = Color.rgb(0x00, 0x00, 0x00); 13 | c4Blue = Color.rgb(0x00, 0x00, 0x00); 14 | c5Purple = Color.rgb(0x00, 0x00, 0x00); 15 | c6Cyan = Color.rgb(0x00, 0x00, 0x00); 16 | c7White = Color.rgb(0x00, 0x00, 0x00); 17 | 18 | c9LRed = Color.rgb(0x00, 0x00, 0x00); 19 | caLGreen = Color.rgb(0x77, 0xff, 0x77); 20 | cbLYellow = Color.rgb(0x00, 0x00, 0x00); 21 | ccLBlue = Color.rgb(0x00, 0x00, 0x00); 22 | cdLPurple = Color.rgb(0x00, 0x00, 0x00); 23 | ceLCyan = Color.rgb(0x00, 0x00, 0x00); 24 | cfLWhite = Color.rgb(0x00, 0x00, 0x00); 25 | 26 | levelColors = new int[] { cfLWhite }; 27 | 28 | defaultFontColor = "black"; 29 | defaultBackground = Color.rgb(0xff, 0xff, 0xff); 30 | defaultForeground = Color.rgb(0x10, 0x10, 0x10); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /MobileOrg/src/main/java/com/matburt/mobileorg/gui/theme/WhiteTheme.java: -------------------------------------------------------------------------------- 1 | package com.matburt.mobileorg.gui.theme; 2 | 3 | import android.graphics.Color; 4 | 5 | public class WhiteTheme extends DefaultTheme { 6 | 7 | public WhiteTheme() { 8 | super(); 9 | c0Black = Color.rgb(0xff, 0xff, 0xff); 10 | c1Red = Color.rgb(0x20, 0x00, 0x00); 11 | c2Green = Color.rgb(0x00, 0x20, 0x00); 12 | c3Yellow = Color.rgb(0x20, 0x20, 0x00); 13 | c4Blue = Color.rgb(0x0, 0x0, 0x20); 14 | c5Purple = Color.rgb(0x20, 0x00, 0x20); 15 | c6Cyan = Color.rgb(0x00, 0x20, 0x20); 16 | c7White = Color.rgb(0x10, 0x10, 0x10); 17 | 18 | c9LRed = Color.rgb(0xa0, 0x0, 0x0); 19 | caLGreen = Color.rgb(0x20, 0xa0, 0x20); 20 | cbLYellow = Color.rgb(0x80, 0x80, 0x00); 21 | ccLBlue = Color.rgb(0x00, 0x00, 0x80); 22 | cdLPurple = Color.rgb(0x80, 0x00, 0x80); 23 | ceLCyan = Color.rgb(0x00, 0x80, 0x80); 24 | cfLWhite = Color.rgb(0x00, 0x00, 0x00); 25 | 26 | levelColors = new int[] { ccLBlue, c3Yellow, ceLCyan, c2Green, 27 | c5Purple, ccLBlue, c2Green, ccLBlue, c3Yellow, ceLCyan }; 28 | 29 | defaultFontColor = "black"; 30 | defaultBackground = Color.rgb(0xff, 0xff, 0xff); 31 | defaultForeground = Color.rgb(0x10, 0x10, 0x10); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /MobileOrg/src/main/java/com/matburt/mobileorg/gui/wizard/DirectoryBrowser.java: -------------------------------------------------------------------------------- 1 | package com.matburt.mobileorg.gui.wizard; 2 | 3 | import android.content.Context; 4 | 5 | import com.matburt.mobileorg.R; 6 | 7 | import java.io.File; 8 | import java.util.ArrayList; 9 | 10 | public abstract class DirectoryBrowser { 11 | 12 | protected Context context; 13 | 14 | protected T currentDirectory; 15 | protected ArrayList directoryListing = new ArrayList(); 16 | protected ArrayList directoryNames = new ArrayList(); 17 | 18 | protected String upOneLevel; 19 | 20 | public DirectoryBrowser(Context context) { 21 | this.context = context; 22 | this.upOneLevel = context.getString(R.string.up_one_level); 23 | } 24 | 25 | public abstract void browseTo(int position); 26 | 27 | protected abstract void browseTo(String directory); 28 | 29 | public abstract boolean isCurrentDirectoryRoot(); 30 | 31 | public ArrayList listFiles() { 32 | return directoryNames; 33 | } 34 | 35 | public String getDirectoryName(int position) { 36 | return directoryNames.get(position); 37 | } 38 | 39 | protected T getDir(int position) { 40 | return directoryListing.get(position); 41 | } 42 | 43 | public String getAbsolutePath(int position) { 44 | T directory = directoryListing.get(position); 45 | 46 | if (directory instanceof String) 47 | return (String) directory; 48 | 49 | if (directory instanceof File) 50 | return ((File) directory).getAbsolutePath(); 51 | 52 | return ""; 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /MobileOrg/src/main/java/com/matburt/mobileorg/gui/wizard/FolderAdapter.java: -------------------------------------------------------------------------------- 1 | package com.matburt.mobileorg.gui.wizard; 2 | 3 | import android.content.Context; 4 | import android.view.LayoutInflater; 5 | import android.view.View; 6 | import android.view.ViewGroup; 7 | import android.widget.ArrayAdapter; 8 | import android.widget.Button; 9 | import android.widget.CheckBox; 10 | import android.widget.CompoundButton; 11 | import android.widget.TextView; 12 | 13 | import com.matburt.mobileorg.R; 14 | 15 | import java.util.ArrayList; 16 | 17 | public class FolderAdapter extends ArrayAdapter { 18 | private int currentChecked = -1; 19 | private DirectoryBrowser directory; 20 | private Button doneButton; 21 | 22 | public FolderAdapter(Context context, int resource, ArrayList list) { 23 | super(context, resource, list); 24 | } 25 | 26 | public void setDirectoryBrowser(DirectoryBrowser d) { 27 | directory = d; 28 | } 29 | 30 | public String getCheckedDirectory() { 31 | if (currentChecked == -1) 32 | return ""; 33 | // (Toast.makeText(context, directory.getAbsolutePath(currentChecked), 34 | // Toast.LENGTH_LONG)).show(); 35 | return directory.getAbsolutePath(currentChecked); 36 | } 37 | 38 | public void setDoneButton(Button b) { 39 | doneButton = b; 40 | } 41 | 42 | @Override 43 | public View getView(int position, View convertView, ViewGroup parent) { 44 | View row = convertView; 45 | TextView folder = null; 46 | CheckBox check = null; 47 | if (row == null) { 48 | LayoutInflater inflater = LayoutInflater.from(getContext()); 49 | row = inflater.inflate(R.layout.folder_adapter_row, parent, false); 50 | folder = (TextView) row.findViewById(R.id.folder); 51 | folder.setOnClickListener(new View.OnClickListener() { 52 | 53 | @Override 54 | public void onClick(View folder) { 55 | int position = (Integer) folder.getTag(); 56 | // FolderAdapter.this.clear(); 57 | directory.browseTo(position); 58 | currentChecked = -1; 59 | FolderAdapter.this.notifyDataSetChanged(); 60 | doneButton.setEnabled(false); 61 | } 62 | }); 63 | check = (CheckBox) row.findViewById(R.id.checkbox); 64 | check.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { 65 | 66 | public void onCheckedChanged(CompoundButton buttonView, 67 | boolean isChecked) { 68 | // update last checked position 69 | int position = (Integer) buttonView.getTag(); 70 | if (isChecked) 71 | currentChecked = position; 72 | else if (currentChecked == position) 73 | currentChecked = -1; 74 | FolderAdapter.this.notifyDataSetChanged(); 75 | if (isChecked) 76 | doneButton.setEnabled(true); 77 | } 78 | }); 79 | } 80 | folder = (TextView) row.findViewById(R.id.folder); 81 | folder.setText(directory.getDirectoryName(position)); 82 | folder.setTag(Integer.valueOf(position)); 83 | check = (CheckBox) row.findViewById(R.id.checkbox); 84 | // disable the "Up one level" checkbox; otherwise make sure its enabled 85 | if (position == 0 && !directory.isCurrentDirectoryRoot()) 86 | check.setEnabled(false); 87 | else 88 | check.setEnabled(true); 89 | check.setTag(Integer.valueOf(position)); 90 | // set check state. only one can be checked 91 | boolean status = (currentChecked == position) ? true : false; 92 | check.setChecked(status); 93 | return (row); 94 | } 95 | } 96 | -------------------------------------------------------------------------------- /MobileOrg/src/main/java/com/matburt/mobileorg/gui/wizard/LocalDirectoryBrowser.java: -------------------------------------------------------------------------------- 1 | package com.matburt.mobileorg.gui.wizard; 2 | 3 | import android.content.Context; 4 | 5 | import java.io.File; 6 | import java.util.Arrays; 7 | 8 | public class LocalDirectoryBrowser extends DirectoryBrowser { 9 | 10 | public LocalDirectoryBrowser(Context context) { 11 | super(context); 12 | 13 | browseTo(File.separator); 14 | } 15 | 16 | @Override 17 | public boolean isCurrentDirectoryRoot() { 18 | return currentDirectory.getParent() == null; 19 | } 20 | 21 | @Override 22 | public void browseTo(int position) { 23 | File newdir = getDir(position); 24 | browseTo(newdir.getAbsolutePath()); 25 | } 26 | 27 | @Override 28 | public void browseTo(String directory) { 29 | currentDirectory = new File(directory); 30 | directoryNames.clear(); 31 | directoryListing.clear(); 32 | if (currentDirectory.getParent() != null) { 33 | directoryNames.add(upOneLevel); 34 | directoryListing.add(currentDirectory.getParentFile()); 35 | } 36 | File[] tmpListing = currentDirectory.listFiles(); 37 | // default list order doesn't seem to be alpha 38 | Arrays.sort(tmpListing); 39 | for (File dir : tmpListing) { 40 | if (dir.isDirectory() && dir.canWrite()) { 41 | directoryNames.add(dir.getName()); 42 | directoryListing.add(dir); 43 | } 44 | } 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /MobileOrg/src/main/java/com/matburt/mobileorg/gui/wizard/WideLinearLayout.java: -------------------------------------------------------------------------------- 1 | package com.matburt.mobileorg.gui.wizard; 2 | 3 | import android.content.Context; 4 | import android.util.AttributeSet; 5 | import android.view.View; 6 | import android.view.ViewGroup; 7 | import android.widget.LinearLayout; 8 | 9 | public class WideLinearLayout extends LinearLayout { 10 | 11 | private int screenWidth; 12 | 13 | public WideLinearLayout(Context context) { 14 | super(context); 15 | } 16 | 17 | public WideLinearLayout(Context context, AttributeSet attrs) { 18 | super(context, attrs); 19 | } 20 | 21 | public void setWidth(int w) { 22 | screenWidth = w; 23 | } 24 | 25 | @Override 26 | protected void onMeasure(int w, int h) { 27 | // int width = MeasureSpec.getSize(screenWidth); 28 | int height = MeasureSpec.getSize(h); 29 | // and its children 30 | for (int i = 0; i < getChildCount(); i++) { 31 | View page = getChildAt(i); 32 | // page.measure(screenWidth,hs); 33 | ViewGroup.LayoutParams lp = page.getLayoutParams(); 34 | lp.width = screenWidth; 35 | lp.height = height; 36 | } 37 | // setMeasuredDimension(width,height); 38 | super.onMeasure(w, h); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /MobileOrg/src/main/java/com/matburt/mobileorg/gui/wizard/WizardActivity.java: -------------------------------------------------------------------------------- 1 | package com.matburt.mobileorg.gui.wizard; 2 | 3 | import android.content.Intent; 4 | import android.content.SharedPreferences; 5 | import android.os.Bundle; 6 | import android.preference.PreferenceManager; 7 | import android.support.v7.app.AppCompatActivity; 8 | import android.util.Log; 9 | import android.view.View; 10 | import android.widget.RadioButton; 11 | import android.widget.RadioGroup; 12 | 13 | import com.matburt.mobileorg.OrgNodeListActivity; 14 | import com.matburt.mobileorg.gui.wizard.wizards.DropboxWizard; 15 | import com.matburt.mobileorg.gui.wizard.wizards.SDCardWizard; 16 | import com.matburt.mobileorg.gui.wizard.wizards.SSHWizard; 17 | import com.matburt.mobileorg.gui.wizard.wizards.UbuntuOneWizard; 18 | import com.matburt.mobileorg.gui.wizard.wizards.WebDAVWizard; 19 | import com.matburt.mobileorg.R; 20 | 21 | public class WizardActivity extends AppCompatActivity { 22 | 23 | @Override 24 | public void onCreate(Bundle savedInstanceState) { 25 | super.onCreate(savedInstanceState); 26 | setContentView(R.layout.wizard_choose_synchronizer); 27 | 28 | final RadioGroup syncGroup = (RadioGroup) findViewById(R.id.sync_group); 29 | 30 | SharedPreferences srcPrefs = PreferenceManager 31 | .getDefaultSharedPreferences(this); 32 | String syncSource = srcPrefs.getString("syncSource", "nullSync"); 33 | Log.v("sync", "source : "+ syncSource); 34 | int id = getResources().getIdentifier(syncSource, "id", getPackageName() ); 35 | RadioButton radioButton = (RadioButton) findViewById(id); 36 | if(radioButton != null) radioButton.setChecked(true); 37 | 38 | findViewById(R.id.ok).setOnClickListener(new View.OnClickListener() { 39 | @Override 40 | public void onClick(View view) { 41 | int id = syncGroup.getCheckedRadioButtonId(); 42 | if(id < 0) return; 43 | 44 | // Saving selected synchronizer 45 | SharedPreferences appSettings = PreferenceManager 46 | .getDefaultSharedPreferences(WizardActivity.this); 47 | SharedPreferences.Editor editor = appSettings.edit(); 48 | String syncName = getResources().getResourceEntryName(id); 49 | editor.putString("syncSource", syncName); 50 | editor.apply(); 51 | switch (syncName) { 52 | case "webdav": 53 | startActivity(new Intent(WizardActivity.this, WebDAVWizard.class)); 54 | break; 55 | case "dropbox": 56 | startActivity(new Intent(WizardActivity.this, DropboxWizard.class)); 57 | break; 58 | case "ubuntuone": 59 | startActivity(new Intent(WizardActivity.this, UbuntuOneWizard.class)); 60 | break; 61 | case "sdcard": 62 | startActivity(new Intent(WizardActivity.this, SDCardWizard.class)); 63 | break; 64 | case "ssh": 65 | startActivity(new Intent(WizardActivity.this, SSHWizard.class)); 66 | break; 67 | default: 68 | startActivity(new Intent(WizardActivity.this, OrgNodeListActivity.class)); 69 | break; 70 | } 71 | } 72 | }); 73 | 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /MobileOrg/src/main/java/com/matburt/mobileorg/gui/wizard/wizards/DropboxDirectoryBrowser.java: -------------------------------------------------------------------------------- 1 | package com.matburt.mobileorg.gui.wizard.wizards; 2 | 3 | import android.content.Context; 4 | 5 | import com.dropbox.client2.DropboxAPI; 6 | import com.dropbox.client2.DropboxAPI.Entry; 7 | import com.dropbox.client2.android.AndroidAuthSession; 8 | import com.dropbox.client2.exception.DropboxException; 9 | import com.matburt.mobileorg.gui.wizard.DirectoryBrowser; 10 | 11 | import java.io.File; 12 | 13 | public class DropboxDirectoryBrowser extends DirectoryBrowser { 14 | 15 | private DropboxAPI dropbox; 16 | 17 | DropboxDirectoryBrowser(Context context, 18 | DropboxAPI dropboxApi) { 19 | super(context); 20 | this.dropbox = dropboxApi; 21 | 22 | browseTo(File.separator); 23 | } 24 | 25 | private static String getParentPath(String path) { 26 | int ind = path.lastIndexOf(File.separatorChar); 27 | return path.substring(0, ind + 1); 28 | } 29 | 30 | @Override 31 | public boolean isCurrentDirectoryRoot() { 32 | return currentDirectory.equals(File.separator); 33 | } 34 | 35 | @Override 36 | public void browseTo(int position) { 37 | browseTo(getDir(position)); 38 | } 39 | 40 | @Override 41 | public void browseTo(String directory) { 42 | currentDirectory = directory; 43 | directoryNames.clear(); 44 | directoryListing.clear(); 45 | if (!isCurrentDirectoryRoot()) { 46 | directoryNames.add(upOneLevel); 47 | directoryListing.add(getParentPath(currentDirectory)); 48 | } 49 | 50 | try { 51 | Entry entries = dropbox.metadata(directory, 1000, null, true, null); 52 | 53 | for (Entry e : entries.contents) { 54 | if (e.isDir) { 55 | directoryNames.add(e.fileName()); 56 | directoryListing.add(e.path); 57 | } 58 | } 59 | } catch (DropboxException e) { 60 | // Log.d("MobileOrg", "Failed to list directory for dropbox: " + e.toString()); 61 | } 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /MobileOrg/src/main/java/com/matburt/mobileorg/gui/wizard/wizards/SDCardWizard.java: -------------------------------------------------------------------------------- 1 | package com.matburt.mobileorg.gui.wizard.wizards; 2 | 3 | import android.content.SharedPreferences; 4 | import android.os.Bundle; 5 | import android.preference.PreferenceManager; 6 | import android.support.v7.app.AppCompatActivity; 7 | import android.widget.Button; 8 | import android.widget.ListView; 9 | 10 | import com.matburt.mobileorg.gui.wizard.FolderAdapter; 11 | import com.matburt.mobileorg.gui.wizard.LocalDirectoryBrowser; 12 | import com.matburt.mobileorg.R; 13 | 14 | public class SDCardWizard extends AppCompatActivity { 15 | 16 | private FolderAdapter directoryAdapter; 17 | 18 | @Override 19 | public void onCreate(Bundle savedInstanceState) { 20 | super.onCreate(savedInstanceState); 21 | setContentView(R.layout.wizard_folder_pick_list); 22 | 23 | LocalDirectoryBrowser directory = new LocalDirectoryBrowser(this); 24 | directoryAdapter = new FolderAdapter(this, R.layout.folder_adapter_row, 25 | directory.listFiles()); 26 | directoryAdapter 27 | .setDoneButton((Button) findViewById(R.id.wizard_done_button)); 28 | directoryAdapter.setDirectoryBrowser(directory); 29 | 30 | ListView folderList = (ListView) findViewById(R.id.wizard_folder_list); 31 | folderList.setAdapter(directoryAdapter); 32 | directoryAdapter.notifyDataSetChanged(); 33 | } 34 | 35 | public void saveSettings() { 36 | SharedPreferences appSettings = PreferenceManager 37 | .getDefaultSharedPreferences(this); 38 | SharedPreferences.Editor editor = appSettings.edit(); 39 | 40 | editor.putString("syncSource", "sdcard"); 41 | editor.putString("indexFilePath", 42 | directoryAdapter.getCheckedDirectory()); 43 | 44 | editor.apply(); 45 | finish(); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /MobileOrg/src/main/java/com/matburt/mobileorg/gui/wizard/wizards/UbuntuOneDirectoryBrowser.java: -------------------------------------------------------------------------------- 1 | package com.matburt.mobileorg.gui.wizard.wizards; 2 | 3 | import android.content.Context; 4 | 5 | import com.matburt.mobileorg.gui.wizard.DirectoryBrowser; 6 | import com.matburt.mobileorg.synchronizers.UbuntuOneSynchronizer; 7 | 8 | import java.io.File; 9 | 10 | public class UbuntuOneDirectoryBrowser extends DirectoryBrowser { 11 | private UbuntuOneSynchronizer synchronizer; 12 | 13 | public UbuntuOneDirectoryBrowser(Context context, UbuntuOneSynchronizer synchronizer) { 14 | super(context); 15 | this.synchronizer = synchronizer; 16 | 17 | browseTo(File.separator); 18 | } 19 | 20 | private static String getParentPath(String path) { 21 | if (path.charAt(path.length() - 1) == File.separatorChar) { 22 | path = path.substring(0, path.length() - 1); 23 | } 24 | int ind = path.lastIndexOf(File.separatorChar); 25 | return path.substring(0, ind + 1); 26 | } 27 | 28 | @Override 29 | public boolean isCurrentDirectoryRoot() { 30 | return currentDirectory.equals(File.separator); 31 | } 32 | 33 | @Override 34 | public void browseTo(int position) { 35 | browseTo(getDir(position)); 36 | } 37 | 38 | @Override 39 | public void browseTo(String directory) { 40 | currentDirectory = directory; 41 | directoryNames.clear(); 42 | directoryListing.clear(); 43 | if (!isCurrentDirectoryRoot()) { 44 | directoryNames.add(upOneLevel); 45 | directoryListing.add(getParentPath(currentDirectory)); 46 | // Log.d("MobileOrg", "Current directory: " + currentDirectory); 47 | // Log.d("MobileOrg", "Parent path: " + getParentPath(currentDirectory)); 48 | } 49 | for (String item : synchronizer.getDirectoryList(directory)) { 50 | directoryNames.add(item); 51 | directoryListing.add(item); 52 | } 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /MobileOrg/src/main/java/com/matburt/mobileorg/gui/wizard/wizards/UbuntuOneWizard.java: -------------------------------------------------------------------------------- 1 | package com.matburt.mobileorg.gui.wizard.wizards; 2 | 3 | import android.content.SharedPreferences; 4 | import android.os.Bundle; 5 | import android.os.HandlerThread; 6 | import android.preference.PreferenceManager; 7 | import android.support.v7.app.AppCompatActivity; 8 | import android.view.LayoutInflater; 9 | import android.view.View; 10 | import android.view.View.OnClickListener; 11 | import android.widget.Button; 12 | import android.widget.EditText; 13 | import android.widget.ListView; 14 | 15 | import com.matburt.mobileorg.gui.wizard.FolderAdapter; 16 | import com.matburt.mobileorg.R; 17 | import com.matburt.mobileorg.synchronizers.UbuntuOneSynchronizer; 18 | 19 | public class UbuntuOneWizard extends AppCompatActivity { 20 | 21 | private EditText ubuntuoneEmail; 22 | private EditText ubuntuonePass; 23 | private Button loginButton; 24 | 25 | private boolean isLoggedIn = false; 26 | 27 | private FolderAdapter directoryAdapter; 28 | 29 | 30 | @Override 31 | public void onCreate(Bundle savedInstanceState) { 32 | super.onCreate(savedInstanceState); 33 | setContentView(R.layout.wizard_ubuntuone); 34 | 35 | ubuntuoneEmail = (EditText) findViewById(R.id.wizard_ubuntu_email); 36 | ubuntuonePass = (EditText) findViewById(R.id.wizard_ubuntu_password); 37 | loginButton = (Button) findViewById(R.id.wizard_ubuntu_login_button); 38 | loginButton.setOnClickListener(new OnClickListener() { 39 | @Override 40 | public void onClick(View v) { 41 | if (isLoggedIn == false) { 42 | loginUbuntuOne(); 43 | } 44 | } 45 | }); 46 | } 47 | 48 | 49 | private void loginUbuntuOne() { 50 | final UbuntuOneSynchronizer uos = new UbuntuOneSynchronizer( 51 | this); 52 | uos.username = ubuntuoneEmail.getText().toString(); 53 | uos.password = ubuntuonePass.getText().toString(); 54 | 55 | // move this into another thread, so we don't get an ANR if the network 56 | // is unavailable 57 | Thread uiThread = new HandlerThread("UIHandler"); 58 | uiThread.start(); 59 | // uiHandler = new UIHandler(((HandlerThread) uiThread).getLooper()); 60 | // Toast.makeText(this, "Logging in, please wait", Toast.LENGTH_SHORT).show(); 61 | // if (uos.login()) { 62 | // showToastRemote("Login Successfull"); 63 | // loginButton.setEnabled(false); 64 | // wizardView.enablePage(1); 65 | // uos.getBaseUser(); 66 | // createUbuntuOneList(); 67 | // } else { 68 | // showToastRemote("Login Failed"); 69 | // } 70 | } 71 | 72 | 73 | private View createUbuntuOneList() { 74 | View view = LayoutInflater.from(this).inflate( 75 | R.layout.wizard_folder_pick_list, null); 76 | 77 | UbuntuOneSynchronizer uos = new UbuntuOneSynchronizer(this); 78 | uos.getBaseUser(); 79 | UbuntuOneDirectoryBrowser directory = new UbuntuOneDirectoryBrowser(this, uos); 80 | 81 | directoryAdapter = new FolderAdapter(this, R.layout.folder_adapter_row, 82 | directory.listFiles()); 83 | directoryAdapter 84 | .setDoneButton((Button) view.findViewById(R.id.wizard_done_button)); 85 | 86 | directoryAdapter.setDirectoryBrowser(directory); 87 | 88 | ListView folderList = (ListView) view.findViewById(R.id.wizard_folder_list); 89 | folderList.setAdapter(directoryAdapter); 90 | directoryAdapter.notifyDataSetChanged(); 91 | // debug 92 | // TODO Technically, this should be an async task app may crash 93 | // when list of root items is very long and network connection 94 | // is slow 95 | return view; 96 | } 97 | 98 | public void saveSettings() { 99 | SharedPreferences appSettings = PreferenceManager 100 | .getDefaultSharedPreferences(this); 101 | SharedPreferences.Editor editor = appSettings.edit(); 102 | 103 | editor.putString("syncSource", "ubuntu"); 104 | editor.putString("ubuntuOnePath", 105 | directoryAdapter.getCheckedDirectory() + "/"); 106 | 107 | editor.apply(); 108 | this.finish(); 109 | } 110 | } 111 | -------------------------------------------------------------------------------- /MobileOrg/src/main/java/com/matburt/mobileorg/gui/wizard/wizards/WebDAVWizard.java: -------------------------------------------------------------------------------- 1 | package com.matburt.mobileorg.gui.wizard.wizards; 2 | 3 | import android.os.Bundle; 4 | import android.support.v7.app.AppCompatActivity; 5 | import android.view.View; 6 | import android.widget.Button; 7 | import android.widget.EditText; 8 | 9 | import com.matburt.mobileorg.R; 10 | 11 | public class WebDAVWizard extends AppCompatActivity { 12 | 13 | private EditText webdavUser; 14 | private EditText webdavPass; 15 | private EditText webdavUrl; 16 | 17 | @Override 18 | public void onCreate(Bundle savedInstanceState) { 19 | super.onCreate(savedInstanceState); 20 | setContentView(R.layout.wizard_webdav); 21 | 22 | webdavUser = (EditText) findViewById(R.id.wizard_webdav_username); 23 | webdavPass = (EditText) findViewById(R.id.wizard_webdav_password); 24 | webdavUrl = (EditText) findViewById(R.id.wizard_webdav_url); 25 | Button webdavLoginButton = (Button) findViewById(R.id.wizard_webdav_login_button); 26 | webdavLoginButton.setOnClickListener(new View.OnClickListener() { 27 | @Override 28 | public void onClick(View view) { 29 | // loginWebdav(); 30 | } 31 | }); 32 | } 33 | 34 | 35 | 36 | // public void loginWebdav() { 37 | //// Log.v("webdav", "login"); 38 | // final String urlActual = webdavUrl.getText().toString(); 39 | // final String passActual = webdavPass.getText().toString(); 40 | // final String userActual = webdavUser.getText().toString(); 41 | // progress.show(); 42 | // 43 | // Thread uiThread = new HandlerThread("UIHandler"); 44 | // uiThread.start(); 45 | // uiHandler = new UIHandler(((HandlerThread) uiThread).getLooper()); 46 | // 47 | // Thread loginThread = new Thread() { 48 | // public void run() { 49 | // WebDAVSynchronizer wds = new WebDAVSynchronizer(context); 50 | // String extra = wds.testConnection(urlActual, userActual, 51 | // passActual); 52 | // if (extra != null) { 53 | // showToastRemote("Login failed: " + extra); 54 | // return; 55 | // } 56 | // showToastRemote("Login succeeded"); 57 | // } 58 | // }; 59 | // loginThread.start(); 60 | // } 61 | // 62 | // public void saveSettings() { 63 | // SharedPreferences appSettings = PreferenceManager 64 | // .getDefaultSharedPreferences(context); 65 | // SharedPreferences.Editor editor = appSettings.edit(); 66 | // 67 | // editor.putString("syncSource", "webdav"); 68 | // 69 | // editor.putString("webUrl", webdavUrl.getText().toString()); 70 | // editor.putString("webPass", webdavPass.getText().toString()); 71 | // editor.putString("webUser", webdavUser.getText().toString()); 72 | // 73 | // editor.apply(); 74 | // ((Activity) context).finish(); 75 | // } 76 | } 77 | -------------------------------------------------------------------------------- /MobileOrg/src/main/java/com/matburt/mobileorg/orgdata/CalendarEntry.java: -------------------------------------------------------------------------------- 1 | package com.matburt.mobileorg.orgdata; 2 | 3 | public class CalendarEntry { 4 | public String title = ""; 5 | public String description = ""; 6 | public String location = ""; 7 | public long id = -1; 8 | public long dtStart = 0; 9 | public long dtEnd = 0; 10 | public int allDay = 0; 11 | } 12 | -------------------------------------------------------------------------------- /MobileOrg/src/main/java/com/matburt/mobileorg/orgdata/MobileOrgApplication.java: -------------------------------------------------------------------------------- 1 | package com.matburt.mobileorg.orgdata; 2 | 3 | import android.app.Application; 4 | import android.content.Context; 5 | import android.preference.PreferenceManager; 6 | 7 | import com.matburt.mobileorg.services.SyncService; 8 | import com.matburt.mobileorg.synchronizers.DropboxSynchronizer; 9 | import com.matburt.mobileorg.synchronizers.NullSynchronizer; 10 | import com.matburt.mobileorg.synchronizers.SDCardSynchronizer; 11 | import com.matburt.mobileorg.synchronizers.SSHSynchronizer; 12 | import com.matburt.mobileorg.synchronizers.Synchronizer; 13 | import com.matburt.mobileorg.synchronizers.UbuntuOneSynchronizer; 14 | import com.matburt.mobileorg.synchronizers.WebDAVSynchronizer; 15 | 16 | public class MobileOrgApplication extends Application { 17 | 18 | private static MobileOrgApplication instance; 19 | 20 | public static Context getContext() { 21 | return instance; 22 | } 23 | 24 | @Override 25 | public void onCreate() { 26 | super.onCreate(); 27 | instance = this; 28 | 29 | OrgDatabase.startDB(this); 30 | startSynchronizer(); 31 | OrgFileParser.startParser(this); 32 | SyncService.startAlarm(this); 33 | } 34 | 35 | public void startSynchronizer() { 36 | String syncSource = 37 | PreferenceManager 38 | .getDefaultSharedPreferences(getApplicationContext()) 39 | .getString("syncSource", ""); 40 | Context c = getApplicationContext(); 41 | 42 | if (syncSource.equals("webdav")) 43 | Synchronizer.setInstance(new WebDAVSynchronizer(c)); 44 | else if (syncSource.equals("sdcard")) 45 | Synchronizer.setInstance(new SDCardSynchronizer(c)); 46 | else if (syncSource.equals("dropbox")) 47 | Synchronizer.setInstance(new DropboxSynchronizer(c)); 48 | else if (syncSource.equals("ubuntu")) 49 | Synchronizer.setInstance(new UbuntuOneSynchronizer(c)); 50 | else if (syncSource.equals("scp")) 51 | Synchronizer.setInstance(new SSHSynchronizer(c)); 52 | else 53 | Synchronizer.setInstance(new NullSynchronizer(c)); 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /MobileOrg/src/main/java/com/matburt/mobileorg/orgdata/OrgNodeDate.java: -------------------------------------------------------------------------------- 1 | package com.matburt.mobileorg.orgdata; 2 | 3 | import android.text.format.DateUtils; 4 | 5 | import java.text.ParseException; 6 | import java.text.SimpleDateFormat; 7 | import java.util.Date; 8 | import java.util.regex.Matcher; 9 | import java.util.regex.Pattern; 10 | 11 | public class OrgNodeDate { 12 | 13 | private static final SimpleDateFormat dateTimeformatter = new SimpleDateFormat("yyyy-MM-dd HH:mm"); 14 | private static final SimpleDateFormat dateformatter = new SimpleDateFormat("yyyy-MM-dd"); 15 | private static final int DATE = 1; 16 | private static final int BEGIN_TIME = 2; 17 | private static final int END_TIME = 3; 18 | private static final String datePattern = "(\\d{1,2}\\:\\d{2})"; // d:dd or dd:dd 19 | private static final Pattern schedulePattern = Pattern 20 | .compile("(\\d{4}-\\d{2}-\\d{2})" // YYYY-MM-DD 21 | + "(?:[^\\d]*)" // Strip out month 22 | + datePattern + "?" // Begin time 23 | + "(?:\\-" + datePattern + ")?"); // "-" followed by end time 24 | public long beginTime = 0; 25 | public long endTime = 0; 26 | public int allDay = 0; 27 | public OrgNodeTimeDate.TYPE type; 28 | private String title = ""; 29 | 30 | public OrgNodeDate(String date) throws IllegalArgumentException { 31 | Matcher schedule = schedulePattern.matcher(date); 32 | 33 | if (schedule.find()) { 34 | try { 35 | if (schedule.group(BEGIN_TIME) == null) { // event is an entire day event 36 | this.beginTime = dateformatter.parse(schedule.group(DATE)).getTime(); 37 | 38 | this.endTime = this.beginTime + DateUtils.DAY_IN_MILLIS; 39 | this.allDay = 1; 40 | } else if (schedule.group(BEGIN_TIME) != null && schedule.group(END_TIME) != null) { 41 | this.beginTime = dateTimeformatter.parse(schedule.group(DATE) + " " + schedule.group(BEGIN_TIME)).getTime(); 42 | this.endTime = dateTimeformatter.parse(schedule.group(DATE) + " " + schedule.group(END_TIME)).getTime(); 43 | this.allDay = 0; 44 | } else if (schedule.group(BEGIN_TIME) != null) { 45 | this.beginTime = dateTimeformatter.parse(schedule.group(DATE) + " " + schedule.group(BEGIN_TIME)).getTime(); 46 | this.endTime = beginTime + DateUtils.HOUR_IN_MILLIS; 47 | this.allDay = 0; 48 | } 49 | 50 | return; 51 | } catch (ParseException e) { 52 | // Log.w("MobileOrg", "Unable to parse schedule: " + date); 53 | } 54 | } else 55 | throw new IllegalArgumentException("Could not create date out of entry"); 56 | } 57 | 58 | public static String getDate(long dtStart, long dtEnd, boolean allDay) { 59 | String date; 60 | 61 | if (allDay) 62 | date = dateformatter.format(new Date(dtStart)); 63 | else 64 | date = dateTimeformatter.format(new Date(dtStart)); 65 | 66 | if (dtEnd > 0 && dtStart != dtEnd) { 67 | long timeDiff = dtEnd - dtStart; 68 | 69 | if (timeDiff <= DateUtils.DAY_IN_MILLIS) { 70 | SimpleDateFormat timeformatter = new SimpleDateFormat("HH:mm"); 71 | String endTime = timeformatter.format(new Date(dtEnd)); 72 | 73 | date += "-" + endTime; 74 | } 75 | } 76 | 77 | return date; 78 | } 79 | 80 | static private String getTimestampTypeHint(OrgNodeTimeDate.TYPE type) { 81 | switch (type) { 82 | case Deadline: 83 | return "DL : "; 84 | case Scheduled: 85 | return "SC : "; 86 | default: 87 | return ""; 88 | } 89 | } 90 | 91 | /** 92 | * Whether an event is in the past. True if event ended 24 hours ago or 93 | * sometime in the future. 94 | */ 95 | public boolean isInPast() { 96 | return System.currentTimeMillis() - DateUtils.DAY_IN_MILLIS >= endTime; 97 | } 98 | 99 | public String getTitle() { 100 | return getTimestampTypeHint(this.type) + this.title; 101 | } 102 | 103 | public void setTitle(String title) { 104 | this.title = title; 105 | } 106 | } 107 | -------------------------------------------------------------------------------- /MobileOrg/src/main/java/com/matburt/mobileorg/orgdata/OrgNodeParser.java: -------------------------------------------------------------------------------- 1 | package com.matburt.mobileorg.orgdata; 2 | 3 | import java.util.ArrayList; 4 | import java.util.regex.Matcher; 5 | import java.util.regex.Pattern; 6 | 7 | public class OrgNodeParser { 8 | private static final int TODO_GROUP = 1; 9 | private static final int PRIORITY_GROUP = 2; 10 | private static final int NAME_GROUP = 3; 11 | private static final int TAGS_GROUP = 4; 12 | private static final int AFTER_GROUP = 5; 13 | private static final String patternStart = "^\\s?"; 14 | private static final String patternEnd = "(?:\\[\\#([^]]+)\\]\\s)?" + // Priority 15 | "(.*?)" + // Title 16 | "\\s*" + "(?::([^\\s]+):)?" + // Tags (without trailing spaces) 17 | "(?:\\s*[!\\*])*" + // Habits 18 | "(?:.*)?" + // Before 19 | "(?:.*TITLE:(.*))?" + // After 20 | "$"; // End of line 21 | private Pattern pattern; 22 | 23 | public OrgNodeParser(ArrayList todos) { 24 | final String patternString = patternStart + "(?:(" 25 | + getTodoRegex(todos) + ")\\s)?" + patternEnd; 26 | // Log.v("regex","patternString : "+patternString); 27 | this.pattern = Pattern.compile(patternString); 28 | } 29 | 30 | private static String getTodoRegex(ArrayList todos) { 31 | if (todos.isEmpty()) 32 | return ""; 33 | 34 | StringBuilder result = new StringBuilder(); 35 | for (String todo : todos){ 36 | result.append(todo).append("|"); 37 | } 38 | 39 | result.deleteCharAt(result.length() - 1); 40 | 41 | return result.toString(); 42 | } 43 | 44 | public OrgNode parseLine(final String line, int numberOfStars) { 45 | OrgNode node = new OrgNode(); 46 | node.level = numberOfStars; 47 | 48 | Matcher matcher = pattern.matcher(line); 49 | matcher.region(numberOfStars + 1, line.length()); 50 | if (matcher.find()) { 51 | if (matcher.group(TODO_GROUP) != null) 52 | node.todo = matcher.group(TODO_GROUP); 53 | 54 | node.name = matcher.group(NAME_GROUP); 55 | 56 | if (matcher.group(PRIORITY_GROUP) != null) 57 | node.priority = matcher.group(PRIORITY_GROUP); 58 | 59 | if (matcher.group(TAGS_GROUP) != null) 60 | node.tags = matcher.group(TAGS_GROUP); 61 | 62 | if (matcher.group(AFTER_GROUP) != null) 63 | node.name = matcher.group(AFTER_GROUP).trim() 64 | + ">" + node.name.trim(); 65 | 66 | } else { 67 | // Log.w("MobileOrg", "Title not matched: " + line); 68 | node.name = line; 69 | } 70 | 71 | return node; 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /MobileOrg/src/main/java/com/matburt/mobileorg/plugin/BundleScrubber.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012 two forty four a.m. LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the 5 | * License. You may obtain a copy of the License at 6 | * 7 | * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" 8 | * BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language 9 | * governing permissions and limitations under the License. 10 | */ 11 | 12 | package com.matburt.mobileorg.plugin; 13 | 14 | import android.content.Intent; 15 | import android.os.Bundle; 16 | 17 | /** 18 | * Helper class to scrub Bundles of invalid extras. This is a workaround for an Android bug: 19 | * . 20 | */ 21 | public final class BundleScrubber 22 | { 23 | 24 | /** 25 | * Scrubs Intents for private serializable subclasses in the Intent extras. If the Intent's extras contain a private 26 | * serializable subclass, the Bundle is cleared. The Bundle will not be set to null. If the Bundle is null, has no extras, or 27 | * the extras do not contain a private serializable subclass, the Bundle is not mutated. 28 | * 29 | * @param intent {@code Intent} to scrub. This parameter may be mutated if scrubbing is necessary. This parameter may be null. 30 | * @return true if the Intent was scrubbed, false if the Intent was not modified. 31 | */ 32 | public static boolean scrub(final Intent intent) 33 | { 34 | if (null == intent) 35 | { 36 | return false; 37 | } 38 | 39 | return scrub(intent.getExtras()); 40 | } 41 | 42 | /** 43 | * Scrubs Bundles for private serializable subclasses in the extras. If the Bundle's extras contain a private serializable 44 | * subclass, the Bundle is cleared. If the Bundle is null, has no extras, or the extras do not contain a private serializable 45 | * subclass, the Bundle is not mutated. 46 | * 47 | * @param bundle {@code Bundle} to scrub. This parameter may be mutated if scrubbing is necessary. This parameter may be null. 48 | * @return true if the Bundle was scrubbed, false if the Bundle was not modified. 49 | */ 50 | public static boolean scrub(final Bundle bundle) 51 | { 52 | if (null == bundle) 53 | { 54 | return false; 55 | } 56 | 57 | /* 58 | * Note: This is a hack to work around a private serializable classloader attack 59 | */ 60 | try 61 | { 62 | // if a private serializable exists, this will throw an exception 63 | bundle.containsKey(null); 64 | } 65 | catch (final Exception e) 66 | { 67 | bundle.clear(); 68 | return true; 69 | } 70 | 71 | return false; 72 | } 73 | } -------------------------------------------------------------------------------- /MobileOrg/src/main/java/com/matburt/mobileorg/plugin/PluginBundleManager.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012 two forty four a.m. LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the 5 | * License. You may obtain a copy of the License at 6 | * 7 | * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" 8 | * BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language 9 | * governing permissions and limitations under the License. 10 | */ 11 | 12 | package com.matburt.mobileorg.plugin; 13 | 14 | import android.os.Bundle; 15 | import android.text.TextUtils; 16 | 17 | /** 18 | * Class for managing the {@link com.twofortyfouram.locale.Intent#EXTRA_BUNDLE} for this plug-in. 19 | */ 20 | public final class PluginBundleManager 21 | { 22 | /** 23 | * Type: {@code String} 24 | *

25 | * String message to display in a Toast message. 26 | */ 27 | public static final String BUNDLE_EXTRA_STRING_MESSAGE = "com.yourcompany.yourapp.extra.STRING_MESSAGE"; //$NON-NLS-1$ 28 | /** 29 | * Type: {@code int} 30 | *

31 | * versionCode of the plug-in that saved the Bundle. 32 | */ 33 | /* 34 | * This extra is not strictly required, however it makes backward and forward compatibility significantly easier. For example, 35 | * suppose a bug is found in how some version of the plug-in stored its Bundle. By having the version, the plug-in can better 36 | * detect when such bugs occur. 37 | */ 38 | public static final String BUNDLE_EXTRA_INT_VERSION_CODE = "com.yourcompany.yourcondition.extra.INT_VERSION_CODE"; //$NON-NLS-1$ 39 | 40 | /** 41 | * Private constructor prevents instantiation 42 | * 43 | * @throws UnsupportedOperationException because this class cannot be instantiated. 44 | */ 45 | private PluginBundleManager() { 46 | throw new UnsupportedOperationException("This class is non-instantiable"); //$NON-NLS-1$ 47 | } 48 | 49 | /** 50 | * Method to verify the content of the bundle are correct. 51 | *

52 | * This method will not mutate {@code bundle}. 53 | * 54 | * @param bundle bundle to verify. May be null, which will always return false. 55 | * @return true if the Bundle is valid, false if the bundle is invalid. 56 | */ 57 | public static boolean isBundleValid(final Bundle bundle) 58 | { 59 | if (null == bundle) 60 | { 61 | return false; 62 | } 63 | 64 | /* 65 | * Make sure the expected extras exist 66 | */ 67 | if (!bundle.containsKey(BUNDLE_EXTRA_STRING_MESSAGE)) 68 | { 69 | return false; 70 | } 71 | if (!bundle.containsKey(BUNDLE_EXTRA_INT_VERSION_CODE)) 72 | { 73 | return false; 74 | } 75 | 76 | /* 77 | * Make sure the correct number of extras exist. Run this test after checking for specific Bundle extras above so that the 78 | * error message is more useful. (E.g. the caller will see what extras are missing, rather than just a message that there 79 | * is the wrong number). 80 | */ 81 | if (2 != bundle.keySet().size()) 82 | { 83 | return false; 84 | } 85 | 86 | /* 87 | * Make sure the extra isn't null or empty 88 | */ 89 | if (TextUtils.isEmpty(bundle.getString(BUNDLE_EXTRA_STRING_MESSAGE))) 90 | { 91 | return false; 92 | } 93 | 94 | /* 95 | * Make sure the extra is the correct type 96 | */ 97 | if (bundle.getInt(BUNDLE_EXTRA_INT_VERSION_CODE, 0) != bundle.getInt(BUNDLE_EXTRA_INT_VERSION_CODE, 1)) 98 | { 99 | return false; 100 | } 101 | 102 | return true; 103 | } 104 | } -------------------------------------------------------------------------------- /MobileOrg/src/main/java/com/matburt/mobileorg/plugin/Synchronize.java: -------------------------------------------------------------------------------- 1 | package com.matburt.mobileorg.plugin; 2 | 3 | import android.content.BroadcastReceiver; 4 | import android.content.Context; 5 | import android.content.Intent; 6 | 7 | import com.matburt.mobileorg.services.SyncService; 8 | 9 | public final class Synchronize extends BroadcastReceiver 10 | { 11 | @Override 12 | public void onReceive(final Context context, final Intent intent) { 13 | context.startService(new Intent(context, SyncService.class)); 14 | } 15 | } -------------------------------------------------------------------------------- /MobileOrg/src/main/java/com/matburt/mobileorg/settings/synchronizers/SDCardSettingsActivity.java: -------------------------------------------------------------------------------- 1 | package com.matburt.mobileorg.settings.synchronizers; 2 | 3 | import android.content.SharedPreferences; 4 | import android.content.SharedPreferences.OnSharedPreferenceChangeListener; 5 | import android.os.Bundle; 6 | import android.preference.Preference; 7 | import android.preference.PreferenceActivity; 8 | import android.preference.PreferenceManager; 9 | 10 | import com.matburt.mobileorg.R; 11 | 12 | public class SDCardSettingsActivity extends PreferenceActivity implements OnSharedPreferenceChangeListener 13 | { 14 | public static final String KEY_INDEX_FILE_PATH = "indexFilePath"; 15 | 16 | @Override 17 | protected void onCreate(Bundle savedInstanceState) { 18 | super.onCreate(savedInstanceState); 19 | addPreferencesFromResource(R.xml.sdsync_preferences); 20 | setPreferenceSummary(PreferenceManager.getDefaultSharedPreferences(this), KEY_INDEX_FILE_PATH); 21 | } 22 | 23 | @Override 24 | public void onPause() { 25 | getPreferenceScreen().getSharedPreferences().unregisterOnSharedPreferenceChangeListener(this); 26 | super.onPause(); 27 | } 28 | 29 | @Override 30 | public void onResume() { 31 | super.onResume(); 32 | getPreferenceScreen().getSharedPreferences().registerOnSharedPreferenceChangeListener(this); 33 | } 34 | 35 | @Override 36 | public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, 37 | String key) { 38 | // Set up the initial values following the Settings design guidelines for Ice Cream Sandwich 39 | // Settings should show their current value instead of a description 40 | setPreferenceSummary(sharedPreferences, key); 41 | } 42 | 43 | protected void setPreferenceSummary(SharedPreferences sharedPreferences, String key) { 44 | Preference pref = findPreference(key); 45 | if (pref != null) { 46 | if (key.equals(KEY_INDEX_FILE_PATH)) { 47 | String value = sharedPreferences.getString(key, ""); 48 | pref.setSummary(value); 49 | } 50 | } 51 | } 52 | } -------------------------------------------------------------------------------- /MobileOrg/src/main/java/com/matburt/mobileorg/settings/synchronizers/ScpSettingsActivity.java: -------------------------------------------------------------------------------- 1 | package com.matburt.mobileorg.settings.synchronizers; 2 | 3 | import android.content.SharedPreferences; 4 | import android.content.SharedPreferences.OnSharedPreferenceChangeListener; 5 | import android.os.Bundle; 6 | import android.preference.Preference; 7 | import android.preference.PreferenceActivity; 8 | import android.preference.PreferenceManager; 9 | 10 | import com.matburt.mobileorg.R; 11 | 12 | public class ScpSettingsActivity extends PreferenceActivity implements OnSharedPreferenceChangeListener 13 | { 14 | public static final String KEY_SCP_PATH = "scpPath"; 15 | public static final String KEY_SCP_PORT = "scpPort"; 16 | public static final String KEY_SCP_USER = "scpUser"; 17 | public static final String KEY_SCP_HOST = "scpHost"; 18 | @Override 19 | protected void onCreate(Bundle savedInstanceState) { 20 | super.onCreate(savedInstanceState); 21 | addPreferencesFromResource(R.xml.scp_preferences); 22 | SharedPreferences shared = PreferenceManager.getDefaultSharedPreferences(this); 23 | setPreferenceSummary(shared, KEY_SCP_PATH); 24 | setPreferenceSummary(shared, KEY_SCP_PORT); 25 | setPreferenceSummary(shared, KEY_SCP_USER); 26 | setPreferenceSummary(shared, KEY_SCP_HOST); 27 | } 28 | 29 | @Override 30 | public void onPause() { 31 | getPreferenceScreen().getSharedPreferences().unregisterOnSharedPreferenceChangeListener(this); 32 | super.onPause(); 33 | } 34 | 35 | @Override 36 | public void onResume() { 37 | super.onResume(); 38 | getPreferenceScreen().getSharedPreferences().registerOnSharedPreferenceChangeListener(this); 39 | } 40 | 41 | @Override 42 | public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, 43 | String key) { 44 | // Set up the initial values following the Settings design guidelines for Ice Cream Sandwich 45 | // Settings should show their current value instead of a description 46 | setPreferenceSummary(sharedPreferences, key); 47 | } 48 | 49 | protected void setPreferenceSummary(SharedPreferences sharedPreferences, String key) { 50 | Preference pref = findPreference(key); 51 | if (pref != null) { 52 | if (key.equals(KEY_SCP_PATH) || key.equals(KEY_SCP_PORT) || key.equals(KEY_SCP_HOST) || key.equals(KEY_SCP_USER)) { 53 | String value = sharedPreferences.getString(key, ""); 54 | pref.setSummary(value); 55 | } 56 | } 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /MobileOrg/src/main/java/com/matburt/mobileorg/settings/synchronizers/UbuntuOneSettingsActivity.java: -------------------------------------------------------------------------------- 1 | package com.matburt.mobileorg.settings.synchronizers; 2 | 3 | import android.content.SharedPreferences; 4 | import android.content.SharedPreferences.OnSharedPreferenceChangeListener; 5 | import android.os.Bundle; 6 | import android.preference.Preference; 7 | import android.preference.Preference.OnPreferenceClickListener; 8 | import android.preference.PreferenceActivity; 9 | import android.preference.PreferenceManager; 10 | 11 | import com.matburt.mobileorg.R; 12 | 13 | public class UbuntuOneSettingsActivity extends PreferenceActivity implements OnPreferenceClickListener, OnSharedPreferenceChangeListener 14 | { 15 | public static final String KEY_UBUNTUONE_PATH = "ubuntuonePath"; 16 | 17 | @Override 18 | protected void onCreate(Bundle savedInstanceState) { 19 | super.onCreate(savedInstanceState); 20 | addPreferencesFromResource(R.xml.ubuntuone_preferences); 21 | setPreferenceSummary(PreferenceManager.getDefaultSharedPreferences(this), KEY_UBUNTUONE_PATH); 22 | } 23 | 24 | public boolean onPreferenceClick(Preference p) { 25 | return true; 26 | } 27 | @Override 28 | public void onPause() { 29 | getPreferenceScreen().getSharedPreferences().unregisterOnSharedPreferenceChangeListener(this); 30 | super.onPause(); 31 | } 32 | 33 | @Override 34 | public void onResume() { 35 | super.onResume(); 36 | getPreferenceScreen().getSharedPreferences().registerOnSharedPreferenceChangeListener(this); 37 | } 38 | 39 | @Override 40 | public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, 41 | String key) { 42 | // Set up the initial values following the Settings design guidelines for Ice Cream Sandwich 43 | // Settings should show their current value instead of a description 44 | setPreferenceSummary(sharedPreferences, key); 45 | } 46 | 47 | protected void setPreferenceSummary(SharedPreferences sharedPreferences, String key) { 48 | Preference pref = findPreference(key); 49 | if (pref != null) { 50 | if (key.equals(KEY_UBUNTUONE_PATH)) { 51 | String value = sharedPreferences.getString(key, ""); 52 | pref.setSummary(value); 53 | } 54 | } 55 | } 56 | } -------------------------------------------------------------------------------- /MobileOrg/src/main/java/com/matburt/mobileorg/settings/synchronizers/WebDAVSettingsActivity.java: -------------------------------------------------------------------------------- 1 | package com.matburt.mobileorg.settings.synchronizers; 2 | 3 | import android.content.SharedPreferences; 4 | import android.content.SharedPreferences.OnSharedPreferenceChangeListener; 5 | import android.os.Bundle; 6 | import android.preference.Preference; 7 | import android.preference.PreferenceActivity; 8 | import android.preference.PreferenceManager; 9 | 10 | import com.matburt.mobileorg.R; 11 | 12 | public class WebDAVSettingsActivity extends PreferenceActivity implements OnSharedPreferenceChangeListener 13 | { 14 | public static final String KEY_WEB_URL = "webUrl"; 15 | public static final String KEY_WEB_USER = "webUser"; 16 | public static final String KEY_WEB_PASS = "webPass"; 17 | 18 | @Override 19 | protected void onCreate(Bundle savedInstanceState) { 20 | super.onCreate(savedInstanceState); 21 | addPreferencesFromResource(R.xml.webdav_preferences); 22 | SharedPreferences shared = PreferenceManager.getDefaultSharedPreferences(this); 23 | setPreferenceSummary(shared, KEY_WEB_URL); 24 | setPreferenceSummary(shared, KEY_WEB_USER); 25 | } 26 | @Override 27 | public void onPause() { 28 | getPreferenceScreen().getSharedPreferences().unregisterOnSharedPreferenceChangeListener(this); 29 | super.onPause(); 30 | } 31 | 32 | @Override 33 | public void onResume() { 34 | super.onResume(); 35 | getPreferenceScreen().getSharedPreferences().registerOnSharedPreferenceChangeListener(this); 36 | } 37 | 38 | @Override 39 | public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, 40 | String key) { 41 | // Set up the initial values following the Settings design guidelines for Ice Cream Sandwich 42 | // Settings should show their current value instead of a description 43 | setPreferenceSummary(sharedPreferences, key); 44 | } 45 | 46 | protected void setPreferenceSummary(SharedPreferences sharedPreferences, String key) { 47 | Preference pref = findPreference(key); 48 | if (pref != null) { 49 | if (key.equals(KEY_WEB_URL) || key.equals(KEY_WEB_USER)) { 50 | String value = sharedPreferences.getString(key, ""); 51 | pref.setSummary(value); 52 | } 53 | } 54 | } 55 | } -------------------------------------------------------------------------------- /MobileOrg/src/main/java/com/matburt/mobileorg/synchronizers/AuthData.java: -------------------------------------------------------------------------------- 1 | package com.matburt.mobileorg.synchronizers; 2 | 3 | import android.content.Context; 4 | import android.content.SharedPreferences; 5 | import android.preference.PreferenceManager; 6 | 7 | import com.matburt.mobileorg.util.FileUtils; 8 | import com.matburt.mobileorg.util.OrgUtils; 9 | 10 | /** 11 | * Created by bcoste on 17/06/16. 12 | */ 13 | public class AuthData { 14 | static AuthData mAuthData = null; 15 | private SharedPreferences appSettings; 16 | 17 | private AuthData(Context context) { 18 | this.appSettings = PreferenceManager 19 | .getDefaultSharedPreferences(context.getApplicationContext()); 20 | } 21 | 22 | public static AuthData getInstance(Context context) { 23 | if (mAuthData == null) mAuthData = new AuthData(context); 24 | return mAuthData; 25 | } 26 | 27 | public boolean usePassword() { 28 | return appSettings.getBoolean("usePassword", true); 29 | } 30 | 31 | public String getPath() { 32 | return OrgUtils.rStrip(appSettings.getString("scpPath", "")); 33 | } 34 | 35 | public String getUser() { 36 | return OrgUtils.rStrip(appSettings.getString("scpUser", "")); 37 | } 38 | 39 | public String getHost() { 40 | return OrgUtils.rStrip(appSettings.getString("scpHost", "")); 41 | } 42 | 43 | public Integer getPort() { 44 | return Integer.parseInt(appSettings.getString("scpPort", "")); 45 | } 46 | 47 | public String getPassword() { 48 | return OrgUtils.rStrip(appSettings.getString("scpPass", "")); 49 | } 50 | 51 | static public String PRIVATE_KEY = "dsa"; 52 | static public String PUBLIC_KEY = PRIVATE_KEY + ".pub"; 53 | 54 | public static String getPrivateKeyPath(Context context){ 55 | return context.getFilesDir().getAbsoluteFile() + "/" + PRIVATE_KEY; 56 | } 57 | 58 | public static String getPublicKeyPath(Context context){ 59 | return context.getFilesDir().getAbsoluteFile() + "/" + PUBLIC_KEY; 60 | } 61 | 62 | public static String getPublicKey(Context context){ 63 | return FileUtils.read(context, getPublicKeyPath(context)); 64 | } 65 | 66 | 67 | } 68 | -------------------------------------------------------------------------------- /MobileOrg/src/main/java/com/matburt/mobileorg/synchronizers/CredentialsProviderAllowHost.java: -------------------------------------------------------------------------------- 1 | package com.matburt.mobileorg.synchronizers; 2 | 3 | import android.content.Context; 4 | import android.widget.TextView; 5 | import android.widget.Toast; 6 | 7 | import com.jcraft.jsch.JSch; 8 | import com.jcraft.jsch.JSchException; 9 | import com.jcraft.jsch.KeyPair; 10 | import com.matburt.mobileorg.R; 11 | import com.matburt.mobileorg.util.FileUtils; 12 | 13 | import org.eclipse.jgit.errors.UnsupportedCredentialItem; 14 | import org.eclipse.jgit.transport.CredentialItem; 15 | import org.eclipse.jgit.transport.CredentialsProvider; 16 | import org.eclipse.jgit.transport.URIish; 17 | 18 | import java.io.BufferedReader; 19 | import java.io.File; 20 | import java.io.FileNotFoundException; 21 | import java.io.FileReader; 22 | import java.io.IOException; 23 | import java.util.Arrays; 24 | 25 | public class CredentialsProviderAllowHost extends CredentialsProvider { 26 | private String username; 27 | 28 | private char[] password; 29 | 30 | /** 31 | * Initialize the provider with a single username and password. 32 | * 33 | * @param username 34 | * @param password 35 | */ 36 | public CredentialsProviderAllowHost(String username, String password) { 37 | this(username, password.toCharArray()); 38 | } 39 | 40 | /** 41 | * Initialize the provider with a single username and password. 42 | * 43 | * @param username 44 | * @param password 45 | */ 46 | public CredentialsProviderAllowHost(String username, char[] password) { 47 | this.username = username; 48 | this.password = password; 49 | } 50 | 51 | @Override 52 | public boolean isInteractive() { 53 | return false; 54 | } 55 | 56 | @Override 57 | public boolean supports(CredentialItem... items) { 58 | for (CredentialItem i : items) { 59 | if (i instanceof CredentialItem.Username) 60 | continue; 61 | else if (i instanceof CredentialItem.Password) 62 | continue; 63 | else return (i instanceof CredentialItem.YesNoType); 64 | } 65 | return true; 66 | } 67 | 68 | @Override 69 | public boolean get(URIish uri, CredentialItem... items) 70 | throws UnsupportedCredentialItem { 71 | for (CredentialItem i : items) { 72 | if (i instanceof CredentialItem.Username) { 73 | ((CredentialItem.Username) i).setValue(username); 74 | continue; 75 | } 76 | if (i instanceof CredentialItem.Password) { 77 | ((CredentialItem.Password) i).setValue(password); 78 | continue; 79 | } 80 | if (i instanceof CredentialItem.StringType) { 81 | if (i.getPromptText().equals("Password: ")) { 82 | ((CredentialItem.StringType) i).setValue(new String( 83 | password)); 84 | continue; 85 | } 86 | } 87 | if (i instanceof CredentialItem.YesNoType) { 88 | ((CredentialItem.YesNoType) i).setValue(true); 89 | continue; 90 | } 91 | throw new UnsupportedCredentialItem(uri, i.getClass().getName() 92 | + ":" + i.getPromptText()); 93 | } 94 | return true; 95 | } 96 | 97 | /** Destroy the saved username and password.. */ 98 | public void clear() { 99 | username = null; 100 | 101 | if (password != null) { 102 | Arrays.fill(password, (char) 0); 103 | password = null; 104 | } 105 | } 106 | } 107 | -------------------------------------------------------------------------------- /MobileOrg/src/main/java/com/matburt/mobileorg/synchronizers/MergeDialogFragment.java: -------------------------------------------------------------------------------- 1 | package com.matburt.mobileorg.synchronizers; 2 | 3 | import android.app.Dialog; 4 | import android.content.DialogInterface; 5 | import android.os.Bundle; 6 | import android.support.v4.app.DialogFragment; 7 | import android.support.v7.app.AlertDialog; 8 | 9 | import com.matburt.mobileorg.R; 10 | 11 | /** 12 | * Created by bcoste on 19/06/16. 13 | */ 14 | public class MergeDialogFragment extends DialogFragment { 15 | 16 | 17 | public MergeDialogFragment(){ 18 | } 19 | 20 | @Override 21 | public Dialog onCreateDialog(Bundle savedInstanceState) { 22 | CharSequence[] conflictedFiles = getActivity().getIntent().getCharSequenceArrayExtra(JGitWrapper.CONFLICT_FILES); 23 | AlertDialog.Builder builder = new AlertDialog.Builder(getActivity()); 24 | builder.setTitle(R.string.sync_git_merge_files) 25 | .setItems(conflictedFiles, new DialogInterface.OnClickListener() { 26 | public void onClick(DialogInterface dialog, int which) { 27 | // The 'which' argument contains the index position 28 | // of the selected item 29 | } 30 | }); 31 | return builder.create(); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /MobileOrg/src/main/java/com/matburt/mobileorg/synchronizers/NullSynchronizer.java: -------------------------------------------------------------------------------- 1 | package com.matburt.mobileorg.synchronizers; 2 | 3 | import android.content.Context; 4 | 5 | import java.io.BufferedReader; 6 | 7 | public class NullSynchronizer extends Synchronizer { 8 | 9 | public NullSynchronizer(Context context) { 10 | super(context); 11 | } 12 | 13 | @Override 14 | public String getRelativeFilesDir() { 15 | return null; 16 | } 17 | 18 | public boolean isConfigured() { 19 | return true; 20 | } 21 | 22 | public void putRemoteFile(String filename, String contents) { 23 | } 24 | 25 | public BufferedReader getRemoteFile(String filename) { 26 | return null; 27 | } 28 | 29 | @Override 30 | public SyncResult synchronize() { 31 | return new SyncResult(); 32 | } 33 | 34 | 35 | @Override 36 | public void postSynchronize() { 37 | } 38 | 39 | @Override 40 | public void addFile(String filename) { 41 | 42 | } 43 | 44 | @Override 45 | public boolean isConnectable() { 46 | return true; 47 | } 48 | } -------------------------------------------------------------------------------- /MobileOrg/src/main/java/com/matburt/mobileorg/synchronizers/ProgressDialogAsyncTask.java: -------------------------------------------------------------------------------- 1 | package com.matburt.mobileorg.synchronizers; 2 | 3 | 4 | import android.app.ProgressDialog; 5 | import android.content.Context; 6 | import android.os.AsyncTask; 7 | 8 | abstract public class ProgressDialogAsyncTask extends AsyncTask { 9 | protected Context context; 10 | private ProgressDialog progress; 11 | 12 | public ProgressDialogAsyncTask(Context context) { 13 | this.context = context; 14 | } 15 | 16 | protected abstract void _onPreExecute(); 17 | 18 | protected abstract void _onPostExecute(Result result); 19 | 20 | @Override 21 | protected void onPreExecute() { 22 | super.onPreExecute(); 23 | _onPreExecute(); 24 | // progress = new ProgressDialog(context); 25 | // progress.setMessage(context.getString(R.string.please_wait)); 26 | // progress.setTitle(context.getString(R.string.signing_in)); 27 | // progress.show(); 28 | } 29 | 30 | @Override 31 | protected void onPostExecute(Result result) { 32 | // progress.dismiss(); 33 | _onPostExecute(result); 34 | } 35 | } -------------------------------------------------------------------------------- /MobileOrg/src/main/java/com/matburt/mobileorg/synchronizers/SDCardSynchronizer.java: -------------------------------------------------------------------------------- 1 | package com.matburt.mobileorg.synchronizers; 2 | 3 | import android.content.Context; 4 | import android.preference.PreferenceManager; 5 | 6 | import java.io.BufferedReader; 7 | import java.io.BufferedWriter; 8 | import java.io.File; 9 | import java.io.FileInputStream; 10 | import java.io.FileNotFoundException; 11 | import java.io.FileWriter; 12 | import java.io.IOException; 13 | import java.io.InputStreamReader; 14 | 15 | public class SDCardSynchronizer extends Synchronizer { 16 | 17 | private String remoteIndexPath; 18 | private String remotePath; 19 | 20 | public SDCardSynchronizer(Context context) { 21 | super(context); 22 | this.remoteIndexPath = PreferenceManager.getDefaultSharedPreferences( 23 | context).getString("indexFilePath", ""); 24 | 25 | this.remotePath = new File(remoteIndexPath) + "/"; 26 | } 27 | 28 | 29 | @Override 30 | public String getRelativeFilesDir() { 31 | return null; 32 | } 33 | 34 | public boolean isConfigured() { 35 | return !remoteIndexPath.equals(""); 36 | } 37 | 38 | public void putRemoteFile(String filename, String contents) throws IOException { 39 | String outfilePath = this.remotePath + filename; 40 | 41 | File file = new File(outfilePath); 42 | BufferedWriter writer = new BufferedWriter(new FileWriter(file, true)); 43 | writer.write(contents); 44 | writer.close(); 45 | } 46 | 47 | public BufferedReader getRemoteFile(String filename) throws FileNotFoundException { 48 | String filePath = this.remotePath + filename; 49 | File file = new File(filePath); 50 | FileInputStream fileIS = new FileInputStream(file); 51 | return new BufferedReader(new InputStreamReader(fileIS)); 52 | } 53 | 54 | @Override 55 | public SyncResult synchronize() { 56 | 57 | return null; 58 | } 59 | 60 | 61 | @Override 62 | public void postSynchronize() { 63 | } 64 | 65 | @Override 66 | public void addFile(String filename) { 67 | 68 | } 69 | 70 | 71 | @Override 72 | public boolean isConnectable() { 73 | return true; 74 | } 75 | } -------------------------------------------------------------------------------- /MobileOrg/src/main/java/com/matburt/mobileorg/synchronizers/SSHSynchronizer.java: -------------------------------------------------------------------------------- 1 | package com.matburt.mobileorg.synchronizers; 2 | 3 | import android.content.Context; 4 | 5 | import com.jcraft.jsch.JSch; 6 | import com.jcraft.jsch.JSchException; 7 | import com.jcraft.jsch.Session; 8 | import com.matburt.mobileorg.util.OrgUtils; 9 | 10 | import org.eclipse.jgit.util.FS; 11 | 12 | import java.io.File; 13 | 14 | public class SSHSynchronizer extends Synchronizer { 15 | private final String LT = "MobileOrg"; 16 | AuthData authData; 17 | private Session session; 18 | 19 | public SSHSynchronizer(Context context) { 20 | super(context); 21 | this.context = context; 22 | authData = AuthData.getInstance(context); 23 | } 24 | 25 | @Override 26 | public String getRelativeFilesDir() { 27 | return JGitWrapper.GIT_DIR; 28 | } 29 | 30 | @Override 31 | public boolean isConfigured() { 32 | return !(authData.getPath().equals("") 33 | || authData.getUser().equals("") 34 | || authData.getHost().equals("") 35 | || authData.getPassword().equals("") 36 | && AuthData.getPublicKey(context).equals("")); 37 | } 38 | 39 | public void connect() { 40 | try { 41 | SshSessionFactory sshSessionFactory = new SshSessionFactory(context); 42 | JSch jSch = sshSessionFactory.createDefaultJSch(FS.detect()); 43 | 44 | 45 | session = jSch.getSession( 46 | authData.getUser(), 47 | authData.getHost(), 48 | authData.getPort()); 49 | 50 | session.setPassword(AuthData.getInstance(context).getPassword()); 51 | 52 | // TODO: find a way to check for host key 53 | // jSch.setKnownHosts("/storage/sdcard0/Download/known_hosts"); 54 | session.setConfig("StrictHostKeyChecking", "no"); 55 | 56 | session.connect(); 57 | session.disconnect(); 58 | } catch (JSchException e) { 59 | e.printStackTrace(); 60 | } 61 | 62 | } 63 | 64 | public SyncResult synchronize(){ 65 | if (isCredentialsRequired()) return new SyncResult(); 66 | SyncResult pullResult = JGitWrapper.pull(context); 67 | 68 | new JGitWrapper.PushTask(context).execute(); 69 | return pullResult; 70 | } 71 | 72 | /** 73 | * Except if authentication by Public Key, the user has to enter his password 74 | * 75 | * @return 76 | */ 77 | public boolean isCredentialsRequired() { 78 | return false; 79 | } 80 | 81 | @Override 82 | public void postSynchronize() { 83 | if (this.session != null) 84 | this.session.disconnect(); 85 | } 86 | 87 | @Override 88 | public void addFile(String filename) { 89 | JGitWrapper.add(filename, context); 90 | } 91 | 92 | @Override 93 | public boolean isConnectable() throws Exception { 94 | if (!OrgUtils.isNetworkOnline(context)) return false; 95 | 96 | this.connect(); 97 | return true; 98 | } 99 | 100 | @Override 101 | public void clearRepository(Context context) { 102 | File dir = new File(getAbsoluteFilesDir(context)); 103 | for (File file : dir.listFiles()) { 104 | if (file.getName().equals(".git")) continue; 105 | file.delete(); 106 | } 107 | } 108 | } 109 | -------------------------------------------------------------------------------- /MobileOrg/src/main/java/com/matburt/mobileorg/synchronizers/SshSessionFactory.java: -------------------------------------------------------------------------------- 1 | package com.matburt.mobileorg.synchronizers; 2 | 3 | import android.content.Context; 4 | import android.widget.Toast; 5 | 6 | import com.jcraft.jsch.JSch; 7 | import com.jcraft.jsch.JSchException; 8 | import com.jcraft.jsch.KeyPair; 9 | import com.jcraft.jsch.Session; 10 | import com.matburt.mobileorg.util.FileUtils; 11 | 12 | import org.eclipse.jgit.transport.JschConfigSessionFactory; 13 | import org.eclipse.jgit.transport.OpenSshConfig; 14 | import org.eclipse.jgit.util.FS; 15 | 16 | import java.io.IOException; 17 | 18 | public class SshSessionFactory extends JschConfigSessionFactory { 19 | Context context; 20 | ConnectionType connection; 21 | 22 | SshSessionFactory(Context context) { 23 | this.context = context; 24 | this.connection = getConnectionType(context); 25 | } 26 | 27 | /** 28 | * Determine if connection if HTTP, SSH+PubKey, SSH+Password 29 | * based on the provided path and whether or not the user has provided a PubKey 30 | * 31 | * @param context 32 | * @return 33 | */ 34 | public static ConnectionType getConnectionType(Context context) { 35 | final AuthData authData = AuthData.getInstance(context); 36 | if (authData.getHost().startsWith("http")) return ConnectionType.kHttp; 37 | else { 38 | if (authData.usePassword()) return ConnectionType.kSshPubKey; 39 | else return ConnectionType.kSshPassword; 40 | } 41 | } 42 | 43 | @Override 44 | protected void configure(OpenSshConfig.Host host, Session session) { 45 | if (connection == ConnectionType.kSshPassword) { 46 | session.setPassword(AuthData.getInstance(context).getPassword()); 47 | } 48 | 49 | } 50 | 51 | @Override 52 | protected JSch createDefaultJSch(FS fs) throws JSchException { 53 | JSch defaultJSch = super.createDefaultJSch(fs); 54 | 55 | if (connection == ConnectionType.kSshPubKey) 56 | defaultJSch.addIdentity(AuthData.getPrivateKeyPath(context)); 57 | 58 | 59 | return defaultJSch; 60 | } 61 | 62 | public static String generateKeyPair(Context context) { 63 | JSch jsch = new JSch(); 64 | 65 | KeyPair kpair = null; 66 | try { 67 | kpair = KeyPair.genKeyPair(jsch, KeyPair.RSA); 68 | kpair.writePrivateKey(context.getFilesDir().getAbsoluteFile() + "/" + AuthData.PRIVATE_KEY); 69 | kpair.writePublicKey(context.getFilesDir().getAbsoluteFile() + "/" + AuthData.PUBLIC_KEY, "MobileOrgPubKey"); 70 | } catch (JSchException | IOException e){ 71 | Toast.makeText(context, e.toString(), Toast.LENGTH_LONG).show(); 72 | return ""; 73 | } 74 | 75 | return AuthData.getPublicKey(context); 76 | } 77 | 78 | enum ConnectionType { 79 | kHttp, 80 | kSshPubKey, 81 | kSshPassword 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /MobileOrg/src/main/java/com/matburt/mobileorg/synchronizers/SyncResult.java: -------------------------------------------------------------------------------- 1 | package com.matburt.mobileorg.synchronizers; 2 | 3 | import java.util.HashSet; 4 | 5 | /** 6 | * Created by bcoste on 18/06/16. 7 | */ 8 | public class SyncResult { 9 | HashSet newFiles; 10 | HashSet changedFiles; 11 | HashSet deletedFiles; 12 | State state; 13 | 14 | SyncResult(){ 15 | newFiles = new HashSet<>(); 16 | changedFiles = new HashSet<>(); 17 | deletedFiles = new HashSet<>(); 18 | state = State.kFailed; 19 | } 20 | 21 | void setState(State state){ 22 | this.state = state; 23 | } 24 | 25 | enum State { 26 | kSuccess, 27 | kFailed 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /MobileOrg/src/main/java/com/matburt/mobileorg/util/MultiMap.java: -------------------------------------------------------------------------------- 1 | package com.matburt.mobileorg.util; 2 | 3 | import java.util.ArrayList; 4 | import java.util.HashMap; 5 | import java.util.Set; 6 | 7 | public class MultiMap { 8 | 9 | private HashMap> entryMap = new HashMap>(); 10 | 11 | public void put(Long key, T value) { 12 | ArrayList valueList = entryMap.get(key); 13 | 14 | if(valueList == null) { 15 | valueList = new ArrayList(); 16 | entryMap.put(key, valueList); 17 | } 18 | 19 | valueList.add(value); 20 | } 21 | 22 | public ArrayList get(Long key) { 23 | return entryMap.get(key); 24 | } 25 | 26 | public void remove(long key, T value) { 27 | ArrayList valueList = entryMap.get(key); 28 | 29 | if(valueList != null) { 30 | valueList.remove(value); 31 | } 32 | } 33 | 34 | public Set keySet() { 35 | return entryMap.keySet(); 36 | } 37 | 38 | public T findValue(long key, Object object) throws IllegalArgumentException { 39 | ArrayList matches = entryMap.get(key); 40 | 41 | if (matches == null) 42 | return null; 43 | 44 | for (T match : matches) { 45 | if (match.equals(object)) 46 | return match; 47 | } 48 | 49 | return null; 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /MobileOrg/src/main/java/com/matburt/mobileorg/util/OrgFileNotFoundException.java: -------------------------------------------------------------------------------- 1 | package com.matburt.mobileorg.util; 2 | 3 | public class OrgFileNotFoundException extends Exception { 4 | private static final long serialVersionUID = -4140326020786885688L; 5 | 6 | public OrgFileNotFoundException() { 7 | super(); 8 | } 9 | 10 | public OrgFileNotFoundException(String message) { 11 | super(message); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /MobileOrg/src/main/java/com/matburt/mobileorg/util/OrgNodeNotFoundException.java: -------------------------------------------------------------------------------- 1 | package com.matburt.mobileorg.util; 2 | 3 | public class OrgNodeNotFoundException extends Exception { 4 | 5 | private static final long serialVersionUID = 6603637490966826497L; 6 | 7 | public OrgNodeNotFoundException() { 8 | super(); 9 | } 10 | 11 | public OrgNodeNotFoundException(String message) { 12 | super(message); 13 | } 14 | 15 | public OrgNodeNotFoundException(OrgFileNotFoundException e) { 16 | super(e); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /MobileOrg/src/main/java/com/matburt/mobileorg/util/TodoDialog.java: -------------------------------------------------------------------------------- 1 | package com.matburt.mobileorg.util; 2 | 3 | import android.content.Context; 4 | import android.content.DialogInterface; 5 | import android.support.v4.content.ContextCompat; 6 | import android.support.v7.app.AlertDialog; 7 | import android.text.Spannable; 8 | import android.text.SpannableString; 9 | import android.text.TextUtils; 10 | import android.text.style.ForegroundColorSpan; 11 | import android.view.View; 12 | import android.widget.Button; 13 | 14 | import com.matburt.mobileorg.orgdata.OrgFile; 15 | import com.matburt.mobileorg.orgdata.OrgNode; 16 | import com.matburt.mobileorg.orgdata.OrgProviderUtils; 17 | import com.matburt.mobileorg.R; 18 | 19 | import java.util.ArrayList; 20 | 21 | public class TodoDialog { 22 | private final Context context; 23 | private final OrgNode node; 24 | private final Button button; 25 | 26 | public TodoDialog(Context _context, OrgNode _node, Button _button, final boolean writeChangeOnTodoChanged) { 27 | this.context = _context; 28 | this.node = _node; 29 | this.button = _button; 30 | 31 | ArrayList todos = PreferenceUtils.getSelectedTodos(); 32 | 33 | if (todos.size() == 0) 34 | todos = OrgProviderUtils.getTodos(context.getContentResolver()); 35 | 36 | ArrayList result = new ArrayList<>(); 37 | result.add("---"); 38 | result.addAll(todos); 39 | 40 | final ArrayList todoList = result; 41 | AlertDialog.Builder builder = new AlertDialog.Builder(context); 42 | builder.setTitle(R.string.todo_state) 43 | .setItems(todoList.toArray(new CharSequence[todoList.size()]), 44 | new DialogInterface.OnClickListener() { 45 | @Override 46 | public void onClick(DialogInterface dialog, 47 | int which) { 48 | String selectedTodo = todoList.get(which); 49 | if(which == 0) selectedTodo = ""; 50 | node.todo = selectedTodo; 51 | setupTodoButton(context,node,button, false); 52 | if(writeChangeOnTodoChanged){ 53 | node.write(context); 54 | OrgFile.updateFile(node, context); 55 | } 56 | } 57 | }); 58 | builder.create().show(); 59 | } 60 | 61 | static public void setupTodoButton(Context context, OrgNode node, 62 | Button button, boolean toggleVisibility) { 63 | String todoString = node.todo; 64 | if(!TextUtils.isEmpty(todoString)) { 65 | Spannable todoSpan = new SpannableString(todoString + " "); 66 | 67 | boolean active = OrgProviderUtils.isTodoActive(todoString, context.getContentResolver()); 68 | 69 | int red = ContextCompat.getColor(context, R.color.colorRed); 70 | int green = ContextCompat.getColor(context, R.color.colorGreen); 71 | // int gray = ContextCompat.getColor(context, R.color.colorGray); 72 | todoSpan.setSpan(new ForegroundColorSpan(active ? red : green), 0, 73 | todoString.length(), 0); 74 | if(toggleVisibility) button.setVisibility(View.VISIBLE); 75 | button.setText(todoSpan); 76 | button.setTextColor(active ? red : green); 77 | } else { 78 | // if(toggleVisibility) button.setVisibility(View.INVISIBLE); 79 | button.setText(""); 80 | button.setTextColor(ContextCompat.getColor(context, R.color.colorLightGray)); 81 | } 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /MobileOrg/src/main/res/drawable-hdpi/ic_dialog_time.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/matburt/mobileorg-android/321062ab3189af8f53059d81176b86f201b86bd9/MobileOrg/src/main/res/drawable-hdpi/ic_dialog_time.png -------------------------------------------------------------------------------- /MobileOrg/src/main/res/drawable-hdpi/ic_menu_add.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/matburt/mobileorg-android/321062ab3189af8f53059d81176b86f201b86bd9/MobileOrg/src/main/res/drawable-hdpi/ic_menu_add.png -------------------------------------------------------------------------------- /MobileOrg/src/main/res/drawable-hdpi/ic_menu_add2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/matburt/mobileorg-android/321062ab3189af8f53059d81176b86f201b86bd9/MobileOrg/src/main/res/drawable-hdpi/ic_menu_add2.png -------------------------------------------------------------------------------- /MobileOrg/src/main/res/drawable-hdpi/ic_menu_agenda.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/matburt/mobileorg-android/321062ab3189af8f53059d81176b86f201b86bd9/MobileOrg/src/main/res/drawable-hdpi/ic_menu_agenda.png -------------------------------------------------------------------------------- /MobileOrg/src/main/res/drawable-hdpi/ic_menu_archive.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/matburt/mobileorg-android/321062ab3189af8f53059d81176b86f201b86bd9/MobileOrg/src/main/res/drawable-hdpi/ic_menu_archive.png -------------------------------------------------------------------------------- /MobileOrg/src/main/res/drawable-hdpi/ic_menu_close_clear_cancel.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/matburt/mobileorg-android/321062ab3189af8f53059d81176b86f201b86bd9/MobileOrg/src/main/res/drawable-hdpi/ic_menu_close_clear_cancel.png -------------------------------------------------------------------------------- /MobileOrg/src/main/res/drawable-hdpi/ic_menu_delete.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/matburt/mobileorg-android/321062ab3189af8f53059d81176b86f201b86bd9/MobileOrg/src/main/res/drawable-hdpi/ic_menu_delete.png -------------------------------------------------------------------------------- /MobileOrg/src/main/res/drawable-hdpi/ic_menu_directions.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/matburt/mobileorg-android/321062ab3189af8f53059d81176b86f201b86bd9/MobileOrg/src/main/res/drawable-hdpi/ic_menu_directions.png -------------------------------------------------------------------------------- /MobileOrg/src/main/res/drawable-hdpi/ic_menu_edit.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/matburt/mobileorg-android/321062ab3189af8f53059d81176b86f201b86bd9/MobileOrg/src/main/res/drawable-hdpi/ic_menu_edit.png -------------------------------------------------------------------------------- /MobileOrg/src/main/res/drawable-hdpi/ic_menu_help.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/matburt/mobileorg-android/321062ab3189af8f53059d81176b86f201b86bd9/MobileOrg/src/main/res/drawable-hdpi/ic_menu_help.png -------------------------------------------------------------------------------- /MobileOrg/src/main/res/drawable-hdpi/ic_menu_home.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/matburt/mobileorg-android/321062ab3189af8f53059d81176b86f201b86bd9/MobileOrg/src/main/res/drawable-hdpi/ic_menu_home.png -------------------------------------------------------------------------------- /MobileOrg/src/main/res/drawable-hdpi/ic_menu_month.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/matburt/mobileorg-android/321062ab3189af8f53059d81176b86f201b86bd9/MobileOrg/src/main/res/drawable-hdpi/ic_menu_month.png -------------------------------------------------------------------------------- /MobileOrg/src/main/res/drawable-hdpi/ic_menu_moreoverflow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/matburt/mobileorg-android/321062ab3189af8f53059d81176b86f201b86bd9/MobileOrg/src/main/res/drawable-hdpi/ic_menu_moreoverflow.png -------------------------------------------------------------------------------- /MobileOrg/src/main/res/drawable-hdpi/ic_menu_preferences.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/matburt/mobileorg-android/321062ab3189af8f53059d81176b86f201b86bd9/MobileOrg/src/main/res/drawable-hdpi/ic_menu_preferences.png -------------------------------------------------------------------------------- /MobileOrg/src/main/res/drawable-hdpi/ic_menu_recent_history.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/matburt/mobileorg-android/321062ab3189af8f53059d81176b86f201b86bd9/MobileOrg/src/main/res/drawable-hdpi/ic_menu_recent_history.png -------------------------------------------------------------------------------- /MobileOrg/src/main/res/drawable-hdpi/ic_menu_refresh.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/matburt/mobileorg-android/321062ab3189af8f53059d81176b86f201b86bd9/MobileOrg/src/main/res/drawable-hdpi/ic_menu_refresh.png -------------------------------------------------------------------------------- /MobileOrg/src/main/res/drawable-hdpi/ic_menu_save.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/matburt/mobileorg-android/321062ab3189af8f53059d81176b86f201b86bd9/MobileOrg/src/main/res/drawable-hdpi/ic_menu_save.png -------------------------------------------------------------------------------- /MobileOrg/src/main/res/drawable-hdpi/ic_menu_search.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/matburt/mobileorg-android/321062ab3189af8f53059d81176b86f201b86bd9/MobileOrg/src/main/res/drawable-hdpi/ic_menu_search.png -------------------------------------------------------------------------------- /MobileOrg/src/main/res/drawable-hdpi/ic_menu_star.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/matburt/mobileorg-android/321062ab3189af8f53059d81176b86f201b86bd9/MobileOrg/src/main/res/drawable-hdpi/ic_menu_star.png -------------------------------------------------------------------------------- /MobileOrg/src/main/res/drawable-hdpi/ic_menu_tag.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/matburt/mobileorg-android/321062ab3189af8f53059d81176b86f201b86bd9/MobileOrg/src/main/res/drawable-hdpi/ic_menu_tag.png -------------------------------------------------------------------------------- /MobileOrg/src/main/res/drawable-hdpi/ic_menu_today.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/matburt/mobileorg-android/321062ab3189af8f53059d81176b86f201b86bd9/MobileOrg/src/main/res/drawable-hdpi/ic_menu_today.png -------------------------------------------------------------------------------- /MobileOrg/src/main/res/drawable-hdpi/ic_menu_view.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/matburt/mobileorg-android/321062ab3189af8f53059d81176b86f201b86bd9/MobileOrg/src/main/res/drawable-hdpi/ic_menu_view.png -------------------------------------------------------------------------------- /MobileOrg/src/main/res/drawable-hdpi/widget_capture.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/matburt/mobileorg-android/321062ab3189af8f53059d81176b86f201b86bd9/MobileOrg/src/main/res/drawable-hdpi/widget_capture.png -------------------------------------------------------------------------------- /MobileOrg/src/main/res/drawable/actionbar_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 16 | 18 | 22 | -------------------------------------------------------------------------------- /MobileOrg/src/main/res/drawable/background_selector.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /MobileOrg/src/main/res/drawable/border.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /MobileOrg/src/main/res/drawable/capture_widget_text_bg.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 10 | 11 | 16 | -------------------------------------------------------------------------------- /MobileOrg/src/main/res/drawable/go_next.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/matburt/mobileorg-android/321062ab3189af8f53059d81176b86f201b86bd9/MobileOrg/src/main/res/drawable/go_next.png -------------------------------------------------------------------------------- /MobileOrg/src/main/res/drawable/go_next_gray.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/matburt/mobileorg-android/321062ab3189af8f53059d81176b86f201b86bd9/MobileOrg/src/main/res/drawable/go_next_gray.png -------------------------------------------------------------------------------- /MobileOrg/src/main/res/drawable/go_next_pressed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/matburt/mobileorg-android/321062ab3189af8f53059d81176b86f201b86bd9/MobileOrg/src/main/res/drawable/go_next_pressed.png -------------------------------------------------------------------------------- /MobileOrg/src/main/res/drawable/go_next_selected.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/matburt/mobileorg-android/321062ab3189af8f53059d81176b86f201b86bd9/MobileOrg/src/main/res/drawable/go_next_selected.png -------------------------------------------------------------------------------- /MobileOrg/src/main/res/drawable/go_previous.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/matburt/mobileorg-android/321062ab3189af8f53059d81176b86f201b86bd9/MobileOrg/src/main/res/drawable/go_previous.png -------------------------------------------------------------------------------- /MobileOrg/src/main/res/drawable/go_previous_gray.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/matburt/mobileorg-android/321062ab3189af8f53059d81176b86f201b86bd9/MobileOrg/src/main/res/drawable/go_previous_gray.png -------------------------------------------------------------------------------- /MobileOrg/src/main/res/drawable/go_previous_pressed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/matburt/mobileorg-android/321062ab3189af8f53059d81176b86f201b86bd9/MobileOrg/src/main/res/drawable/go_previous_pressed.png -------------------------------------------------------------------------------- /MobileOrg/src/main/res/drawable/go_previous_selected.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/matburt/mobileorg-android/321062ab3189af8f53059d81176b86f201b86bd9/MobileOrg/src/main/res/drawable/go_previous_selected.png -------------------------------------------------------------------------------- /MobileOrg/src/main/res/drawable/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/matburt/mobileorg-android/321062ab3189af8f53059d81176b86f201b86bd9/MobileOrg/src/main/res/drawable/icon.png -------------------------------------------------------------------------------- /MobileOrg/src/main/res/drawable/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/matburt/mobileorg-android/321062ab3189af8f53059d81176b86f201b86bd9/MobileOrg/src/main/res/drawable/logo.png -------------------------------------------------------------------------------- /MobileOrg/src/main/res/drawable/outline_item_selected.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /MobileOrg/src/main/res/drawable/timeclock_icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/matburt/mobileorg-android/321062ab3189af8f53059d81176b86f201b86bd9/MobileOrg/src/main/res/drawable/timeclock_icon.png -------------------------------------------------------------------------------- /MobileOrg/src/main/res/drawable/widgetb.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/matburt/mobileorg-android/321062ab3189af8f53059d81176b86f201b86bd9/MobileOrg/src/main/res/drawable/widgetb.png -------------------------------------------------------------------------------- /MobileOrg/src/main/res/drawable/widgetnew9.9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/matburt/mobileorg-android/321062ab3189af8f53059d81176b86f201b86bd9/MobileOrg/src/main/res/drawable/widgetnew9.9.png -------------------------------------------------------------------------------- /MobileOrg/src/main/res/drawable/wizard_next_button.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /MobileOrg/src/main/res/drawable/wizard_previous_button.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /MobileOrg/src/main/res/layout-w900dp/orgnode_list.xml: -------------------------------------------------------------------------------- 1 | 13 | 14 | 19 | 20 | 31 | 32 | 37 | 38 | 39 | -------------------------------------------------------------------------------- /MobileOrg/src/main/res/layout/activity_conflict_resolver.xml: -------------------------------------------------------------------------------- 1 | 9 | 10 | 15 | 16 | 17 | 22 | 23 | 24 | 25 | 31 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | -------------------------------------------------------------------------------- /MobileOrg/src/main/res/layout/activity_orgnode_detail.xml: -------------------------------------------------------------------------------- 1 | 9 | 10 | 15 | 16 | 17 | 22 | 23 | 24 | 25 | 31 | 32 | 33 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /MobileOrg/src/main/res/layout/activity_orgnode_list.xml: -------------------------------------------------------------------------------- 1 | 2 | 9 | 10 | 15 | 16 | 22 | 23 | 24 | 25 | 31 | 32 | 33 | 34 | 35 | 42 | 43 | 44 | 45 | -------------------------------------------------------------------------------- /MobileOrg/src/main/res/layout/agenda.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | -------------------------------------------------------------------------------- /MobileOrg/src/main/res/layout/agenda_header.xml: -------------------------------------------------------------------------------- 1 | 2 | 10 | 11 | -------------------------------------------------------------------------------- /MobileOrg/src/main/res/layout/agenda_recycler_item.xml: -------------------------------------------------------------------------------- 1 | 2 | 10 | 11 | 18 | 19 | 28 | 29 | 36 | 37 | 45 | 46 | -------------------------------------------------------------------------------- /MobileOrg/src/main/res/layout/agendas.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | -------------------------------------------------------------------------------- /MobileOrg/src/main/res/layout/androidauth.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 11 | 12 | 13 | 18 | 19 | 20 | 26 | 27 | 28 |