Commit 532a5a4b authored by Bartek Fabiszewski's avatar Bartek Fabiszewski
Browse files

Configurable track name template, closes #58

parent 75c087e3
Loading
Loading
Loading
Loading
+141 −0
Original line number Diff line number Diff line
/*
 * Copyright (c) 2019 Bartek Fabiszewski
 * http://www.fabiszewski.net
 *
 * This file is part of μlogger-android.
 * Licensed under GPL, either version 3, or any later.
 * See <http://www.gnu.org/licenses/>
 */

package net.fabiszewski.ulogger;

import android.content.Context;
import android.content.SharedPreferences;
import android.text.TextUtils;
import android.util.AttributeSet;

import androidx.annotation.NonNull;
import androidx.preference.PreferenceManager;

import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
import java.util.TimeZone;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

class AutoNamePreference extends TrimmedEditTextPreference {
    private static final Pattern PATTERN = Pattern.compile("%[%ymdHMS]|'");
    private static final Map<String, String> PLACEHOLDERS;
    static {
        Map<String, String> map = new HashMap<>();
        map.put("%%", "%");
        map.put("%y", "yyyy");
        map.put("%m", "MM");
        map.put("%d", "dd");
        map.put("%H", "HH");
        map.put("%M", "mm");
        map.put("%S", "ss");
        map.put("'", "''");
        PLACEHOLDERS = Collections.unmodifiableMap(map);
    }

    public AutoNamePreference(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
        super(context, attrs, defStyleAttr, defStyleRes);
    }

    public AutoNamePreference(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    public AutoNamePreference(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public AutoNamePreference(Context context) {
        super(context);
    }

    /**
     * Returns the summary of this preference. If a {@link SummaryProvider} has been set for this
     * preference, it will be used to provide the summary returned by this method.
     *
     * @return The summary
     * @see #setSummary(CharSequence)
     * @see #setSummaryProvider(SummaryProvider)
     */
    @Override
    public CharSequence getSummary() {
        if ((getSummaryProvider() != null)) {
            final String text = super.getText();
            if (!TextUtils.isEmpty(text)) {
                return getAutoName(text, Calendar.getInstance().getTime());
            }
        }
        return super.getSummary();
    }


    /**
     * Convert user template to SimpleDateFormat pattern
     * User template placeholders: %y (year), %m (month), %d (day),
     * %H (hour), %M (minute), %S (second)
     *
     * @param template User template
     * @return SimpleDateFormat pattern
     */
    @NonNull
    private static String getDateTemplate(@NonNull String template) {
        Matcher matcher = PATTERN.matcher(template);
        StringBuilder sb = new StringBuilder();
        int startPos = 0;
        int endPos;
        final char quot = '\'';
        while (matcher.find()) {
            endPos = matcher.start();
            if (endPos > startPos) {
                sb.append(quot).append(template.substring(startPos, endPos)).append(quot);
            }
            sb.append(PLACEHOLDERS.get(matcher.group()));
            startPos = matcher.end();
        }
        if (startPos < template.length()) {
            sb.append(quot).append(template.substring(startPos)).append(quot);
        }
        return sb.toString();
    }

    /**
     * Get name with pattern format replaced with given date
     *
     * @param template User track name template
     * @param date Date
     * @return String with pattern substituted with current time
     * @throws IllegalArgumentException On illegal pattern
     */
    @NonNull
    static String getAutoName(@NonNull String template, @NonNull Date date) {
        final String pattern = getDateTemplate(template);
        final SimpleDateFormat sdf = new SimpleDateFormat(pattern, Locale.getDefault());
        sdf.setTimeZone(TimeZone.getDefault());
        return sdf.format(date);
    }

    /**
     * Get auto-generated track name
     * Default template: Auto_%y.%m.%d_%H.%M.%S
     *
     * @param context Context
     * @return Track name
     */
    @NonNull
    static String getAutoTrackName(Context context) {
        SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
        String template = prefs.getString(SettingsActivity.KEY_AUTO_NAME, context.getString(R.string.pref_auto_name_default));
        return getAutoName(template, Calendar.getInstance().getTime());
    }
}
+111 −0
Original line number Diff line number Diff line
/*
 * Copyright (c) 2019 Bartek Fabiszewski
 * http://www.fabiszewski.net
 *
 * This file is part of μlogger-android.
 * Licensed under GPL, either version 3, or any later.
 * See <http://www.gnu.org/licenses/>
 */

package net.fabiszewski.ulogger;

import android.app.Dialog;
import android.os.Bundle;
import android.text.Editable;
import android.text.TextWatcher;
import android.view.Gravity;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;

import androidx.annotation.NonNull;
import androidx.appcompat.app.AlertDialog;
import androidx.preference.EditTextPreference;
import androidx.preference.EditTextPreferenceDialogFragmentCompat;

import java.util.Calendar;
import java.util.Date;

public class AutoNamePreferenceDialogFragment extends EditTextPreferenceDialogFragmentCompat implements TextWatcher {
    private EditText editText = null;
    private TextView preview = null;
    private Date TEMPLATE_DATE;

    public static AutoNamePreferenceDialogFragment newInstance(String key) {
        final AutoNamePreferenceDialogFragment fragment = new AutoNamePreferenceDialogFragment();
        final Bundle b = new Bundle(1);
        b.putString(ARG_KEY, key);
        fragment.setArguments(b);
        return fragment;
    }

    @Override
    public void onStart() {
        super.onStart();
        TEMPLATE_DATE = Calendar.getInstance().getTime();
        AlertDialog dialog = (AlertDialog) getDialog();
        if (dialog != null) {
            editText = dialog.findViewById(android.R.id.edit);
            Button positiveButton = dialog.getButton(Dialog.BUTTON_POSITIVE);
            if (positiveButton != null && editText != null) {
                editText.addTextChangedListener(this);
                ViewGroup layout = (ViewGroup) editText.getParent();
                preview = new TextView(getContext());
                layout.addView(preview, layout.indexOfChild(editText));
                preview.setGravity(Gravity.CENTER);
                updatePreview(editText.getText().toString());
                positiveButton.setOnClickListener(v -> {
                    final String template = editText.getText().toString().trim();
                    if (template.isEmpty()) {
                        setError(getString(R.string.empty_trackname_warning));
                    } else {
                        setError(null);
                        EditTextPreference preference = (EditTextPreference) getPreference();
                        preference.setText(template);
                        dismiss();
                    }
                });
            }
        }
    }

    /**
     * Set error on editText
     * @param string Message
     */
    private void setError(String string) {
        if (editText != null) {
            editText.setError(string);
        }
    }

    @Override
    public void beforeTextChanged(CharSequence charSequence, int start, int count, int after) { }

    @Override
    public void onTextChanged(CharSequence charSequence, int start, int before, int count) { }

    @Override
    public void afterTextChanged(Editable editable) {
        updatePreview(editable.toString());
        if (editable.length() == 0) {
            setError(getString(R.string.empty_trackname_warning));
        }
    }

    /**
     * Update preview TextView
     * @param string Preview input string
     */
    private void updatePreview(@NonNull String string) {
        if (preview != null) {
            try {
                preview.setText(AutoNamePreference.getAutoName(string, TEMPLATE_DATE));
            } catch (IllegalArgumentException e) {
                setError(getString(R.string.illegal_template_warning));
            }
        }
    }

}
+0 −22
Original line number Diff line number Diff line
@@ -17,12 +17,10 @@ import android.database.sqlite.SQLiteDatabase;
import android.location.Location;
import android.util.Log;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;

import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Locale;
import java.util.TimeZone;

@@ -294,18 +292,6 @@ class DbAccess {
        return trackName;
    }

    /**
     * Get auto-generated track name (Auto_[yyyy.MM.dd_HH.mm.ss]).
     *
     * @return Track name
     */
    @NonNull
    static String getAutoTrackName() {
        final SimpleDateFormat sdf = new SimpleDateFormat("yyyy.MM.dd_HH.mm.ss", Locale.getDefault());
        sdf.setTimeZone(TimeZone.getDefault());
        final String dateSuffix = sdf.format(Calendar.getInstance().getTime());
        return "Auto_" + dateSuffix;
    }

    /**
     * Update current track, set id.
@@ -334,14 +320,6 @@ class DbAccess {
        db.insert(DbContract.Track.TABLE_NAME, null, values);
    }

    /**
     * Start new track with auto-generated name.
     * @see DbAccess#newTrack(String)
     */
    void newAutoTrack() {
        newTrack(getAutoTrackName());
    }

    /**
     * Get track summary
     *
+1 −1
Original line number Diff line number Diff line
@@ -56,7 +56,7 @@ public class ExternalCommandReceiver extends BroadcastReceiver {
        DbAccess db = DbAccess.getInstance();
        db.open(context);
        if (db.getTrackName() == null) {
            db.newAutoTrack();
            db.newTrack(AutoNamePreference.getAutoTrackName(context));
        }
        db.close();
        Intent intent = new Intent(context, LoggerService.class);
+5 −4
Original line number Diff line number Diff line
@@ -278,7 +278,7 @@ public class MainActivity extends AppCompatActivity {
            Intent intent = new Intent(MainActivity.this, LoggerService.class);
            startService(intent);
        } else {
            showEmptyTrackNameWarning();
            showNoTrackWarning();
        }
    }

@@ -444,8 +444,8 @@ public class MainActivity extends AppCompatActivity {
    /**
     * Display warning if track name is not set
     */
    private void showEmptyTrackNameWarning() {
        showToast(getString(R.string.empty_trackname_warning));
    private void showNoTrackWarning() {
        showToast(getString(R.string.no_track_warning));
    }

    /**
@@ -459,7 +459,7 @@ public class MainActivity extends AppCompatActivity {
        if (editText == null) {
            return;
        }
        editText.setText(DbAccess.getAutoTrackName());
        editText.setText(AutoNamePreference.getAutoTrackName(MainActivity.this));
        editText.setOnClickListener(view -> editText.selectAll());

        final Button submit = dialog.findViewById(R.id.newtrack_button_submit);
@@ -467,6 +467,7 @@ public class MainActivity extends AppCompatActivity {
            submit.setOnClickListener(v -> {
                String trackName = editText.getText().toString();
                if (trackName.length() == 0) {
                    showToast(getString(R.string.empty_trackname_warning), Toast.LENGTH_LONG);
                    return;
                }
                db.newTrack(trackName);
Loading