Srinotes

app/build.gradle

apply plugin: 'com.android.application'

android { namespace "com.ram.srinotes" compileSdkVersion 34

defaultConfig {
    applicationId "com.ram.srinotes"
    minSdkVersion 21
    targetSdkVersion 34
    versionCode 1
    versionName "1.0"
    testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}

buildTypes {
    release {
        minifyEnabled false
        proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
    }
}

buildFeatures {
    viewBinding true
}

compileOptions {
    sourceCompatibility JavaVersion.VERSION_1_8
    targetCompatibility JavaVersion.VERSION_1_8
}

}

dependencies {

implementation "androidx.appcompat:appcompat:1.6.1"
implementation "androidx.constraintlayout:constraintlayout:2.1.4"
implementation "com.google.android.material:material:1.11.0"

implementation "androidx.lifecycle:lifecycle-livedata-ktx:2.6.2"
implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.6.2"

implementation "androidx.room:room-runtime:2.6.1"
annotationProcessor "androidx.room:room-compiler:2.6.1"

implementation "io.noties.markwon:core:4.6.2"
implementation "io.noties.markwon:ext-strikethrough:4.6.2"
implementation "io.noties.markwon:ext-tables:4.6.2"
implementation "io.noties.markwon:ext-tasklist:4.6.2"
implementation "io.noties.markwon:html:4.6.2"
implementation "io.noties.markwon:linkify:4.6.2"

implementation "androidx.recyclerview:recyclerview:1.3.2"
implementation "androidx.cardview:cardview:1.0.0"

testImplementation "junit:junit:4.13.2"
androidTestImplementation "androidx.test.ext:junit:1.1.5"
androidTestImplementation "androidx.test.espresso:espresso-core:3.5.1"

// Jetpack Navigation Component implementation 'androidx.navigation:navigation-fragment:2.7.7' implementation 'androidx.navigation:navigation-ui:2.7.7' }

androidmanifest.xml

<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

<application
    android:icon="@android:drawable/sym_def_app_icon"
    android:label="@string/app_name"
    android:supportsRtl="true"
    android:allowBackup="true"
    android:theme="@style/AppTheme">

    <activity
        android:name=".MainActivity"
        android:exported="true">
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />
            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
    </activity>

</application>

activity_main.xml

<!-- Main content -->
<LinearLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <!-- Toolbar -->
    <com.google.android.material.appbar.MaterialToolbar
        android:id="@+id/toolbar"
        android:layout_width="match_parent"
        android:layout_height="?attr/actionBarSize"
        android:background="?attr/colorPrimary"
        android:elevation="4dp"
        android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
        app:popupTheme="@style/ThemeOverlay.AppCompat.Light"
        app:title="@string/app_name" />

    <!-- Markdown Editor + Preview container -->
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1"
        android:orientation="vertical">

        <com.ram.srinotes.VimEditText
            android:id="@+id/markdownEditor"
            android:layout_width="match_parent"
            android:layout_height="0dp"
            android:layout_weight="1"
            android:gravity="top"
            android:inputType="textMultiLine|textNoSuggestions"
            android:minLines="10"
            android:scrollbars="vertical"
            android:padding="16dp" />

        <androidx.core.widget.NestedScrollView
            android:id="@+id/markdownPreviewContainer"
            android:layout_width="match_parent"
            android:layout_height="0dp"
            android:layout_weight="1"
            android:background="#F5F5F5"
            android:visibility="gone"
            android:padding="16dp">

            <TextView
                android:id="@+id/markdownPreview"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:textColor="#000000" />
        </androidx.core.widget.NestedScrollView>
    </LinearLayout>
</LinearLayout>

<!-- Navigation drawer -->
<com.google.android.material.navigation.NavigationView
    android:id="@+id/nav_view"
    android:layout_width="wrap_content"
    android:layout_height="match_parent"
    android:layout_gravity="start"
    app:headerLayout="@layout/nav_header"
    app:menu="@menu/drawer_menu" />

nav_header.xml

<TextView
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_marginTop="8dp"
    android:text="@string/nav_header_title"
    android:textAppearance="@style/TextAppearance.AppCompat.Body1"
    android:textColor="@android:color/white" />

<TextView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="@string/nav_header_subtitle"
    android:textColor="@android:color/white" />

styles.xml

strings.xml Srinotes Srinotes Your local knowledge base Notes Favorites Trash Save Preview Settings Open Navigation Close Navigation

colours.xml

#6200EE #3700B3 #03DAC5

<color name="purple_500">#6200EE</color>
<color name="purple_700">#3700B3</color>
<color name="teal_200">#03DAC5</color>
<color name="white">#FFFFFF</color>

main activity.java

package com.ram.srinotes;

import android.os.Bundle; import android.view.Menu; import android.view.MenuItem; import android.view.View; import android.widget.TextView; import androidx.appcompat.app.ActionBarDrawerToggle; import androidx.appcompat.app.AppCompatActivity; import androidx.appcompat.widget.Toolbar; import androidx.drawerlayout.widget.DrawerLayout; import androidx.lifecycle.ViewModelProvider; import com.google.android.material.navigation.NavigationView; import io.noties.markwon.Markwon;

public class MainActivity extends AppCompatActivity { private NotesViewModel notesViewModel; private VimEditText markdownEditor; private TextView markdownPreview; private Markwon markwon; private DrawerLayout drawerLayout; private NavigationView navigationView; private ActionBarDrawerToggle toggle;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    Toolbar toolbar = findViewById(R.id.toolbar);
    setSupportActionBar(toolbar);

    drawerLayout = findViewById(R.id.drawer_layout);
    navigationView = findViewById(R.id.nav_view);

    // Setup toggle icon (hamburger)
    toggle = new ActionBarDrawerToggle(
            this, drawerLayout, toolbar,
            R.string.navigation_drawer_open,
            R.string.navigation_drawer_close
    );
    drawerLayout.addDrawerListener(toggle);
    toggle.syncState();

    markdownEditor = findViewById(R.id.markdownEditor);
    markdownPreview = findViewById(R.id.markdownPreview);
    View previewContainer = findViewById(R.id.markdownPreviewContainer);

    markwon = Markwon.create(this);
    notesViewModel = new ViewModelProvider(this).get(NotesViewModel.class);

    markdownEditor.setModeChangeListener(insertMode -> {
        if (insertMode) {
            previewContainer.setVisibility(View.GONE);
            markdownEditor.setVisibility(View.VISIBLE);
            markdownEditor.requestFocus();
        } else {
            markdownEditor.setVisibility(View.GONE);
            previewContainer.setVisibility(View.VISIBLE);
            markwon.setMarkdown(markdownPreview, markdownEditor.getText().toString());
        }
    });

    markdownEditor.setInsertMode(true);
}

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    getMenuInflater().inflate(R.menu.main_menu, menu);
    return true;
}

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    // Let the drawer handle the toggle
    if (toggle.onOptionsItemSelected(item)) {
        return true;
    }

    int id = item.getItemId();

    if (id == R.id.action_save) {
        saveNote();
        return true;
    } else if (id == R.id.action_preview) {
        togglePreview();
        return true;
    }

    return super.onOptionsItemSelected(item);
}

private void saveNote() {
    String content = markdownEditor.getText().toString();
    Note note = new Note();
    note.setContent(content);
    note.setTitle(content.split("\n")[0]); // First line as title
    note.setCreatedAt(System.currentTimeMillis());
    notesViewModel.insert(note);
}

private void togglePreview() {
    markdownEditor.setInsertMode(!markdownEditor.isInsertMode());
}

}