From 2e43a5c0a6176911f0ab86b3c55dd57845b45f30 Mon Sep 17 00:00:00 2001 From: Christian Schneppe Date: Fri, 13 Apr 2018 23:33:56 +0200 Subject: more theme working --- .../java/de/pixart/messenger/ui/AboutActivity.java | 15 ++++- .../messenger/ui/ContactDetailsActivity.java | 10 ++-- .../de/pixart/messenger/ui/RecordingActivity.java | 30 +++++++++- .../de/pixart/messenger/ui/SettingsActivity.java | 21 ++++--- .../pixart/messenger/ui/ShareLocationActivity.java | 2 - .../java/de/pixart/messenger/ui/XmppActivity.java | 15 +++-- .../messenger/ui/adapter/ConversationAdapter.java | 4 +- .../messenger/ui/adapter/ListItemAdapter.java | 6 +- .../messenger/ui/adapter/MessageAdapter.java | 64 +++++++++++++--------- 9 files changed, 110 insertions(+), 57 deletions(-) (limited to 'src/main/java/de/pixart/messenger/ui') diff --git a/src/main/java/de/pixart/messenger/ui/AboutActivity.java b/src/main/java/de/pixart/messenger/ui/AboutActivity.java index ac8b72ec0..e417149d6 100644 --- a/src/main/java/de/pixart/messenger/ui/AboutActivity.java +++ b/src/main/java/de/pixart/messenger/ui/AboutActivity.java @@ -1,17 +1,26 @@ package de.pixart.messenger.ui; import android.os.Bundle; -import android.support.v7.app.AppCompatActivity; import de.pixart.messenger.R; -import static de.pixart.messenger.ui.XmppActivity.configureActionBar; +public class AboutActivity extends XmppActivity { -public class AboutActivity extends AppCompatActivity { + @Override + protected void refreshUiReal() { + + } + + @Override + void onBackendConnected() { + + } @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); + this.mTheme = findTheme(); + setTheme(this.mTheme); setContentView(R.layout.activity_about); setSupportActionBar(findViewById(R.id.toolbar)); configureActionBar(getSupportActionBar()); diff --git a/src/main/java/de/pixart/messenger/ui/ContactDetailsActivity.java b/src/main/java/de/pixart/messenger/ui/ContactDetailsActivity.java index ba9771be1..a42e3a8c0 100644 --- a/src/main/java/de/pixart/messenger/ui/ContactDetailsActivity.java +++ b/src/main/java/de/pixart/messenger/ui/ContactDetailsActivity.java @@ -361,16 +361,18 @@ public class ContactDetailsActivity extends OmemoActivity implements OnAccountUp if (contact == null) { return; } - + int ic_notifications = getThemeResource(R.attr.icon_notifications, R.drawable.ic_notifications_black_24dp); + int ic_notifications_off = getThemeResource(R.attr.icon_notifications_off, R.drawable.ic_notifications_off_black_24dp); + int ic_notifications_paused = getThemeResource(R.attr.icon_notifications_paused, R.drawable.ic_notifications_paused_black_24dp); long mutedTill = mConversation.getLongAttribute(Conversation.ATTRIBUTE_MUTED_TILL, 0); if (mutedTill == Long.MAX_VALUE) { mNotifyStatusText.setText(R.string.notify_never); - mNotifyStatusButton.setImageResource(R.drawable.ic_notifications_off_grey600_24dp); + mNotifyStatusButton.setImageResource(ic_notifications_off); } else if (System.currentTimeMillis() < mutedTill) { mNotifyStatusText.setText(R.string.notify_paused); - mNotifyStatusButton.setImageResource(R.drawable.ic_notifications_paused_grey600_24dp); + mNotifyStatusButton.setImageResource(ic_notifications_paused); } else { - mNotifyStatusButton.setImageResource(R.drawable.ic_notifications_grey600_24dp); + mNotifyStatusButton.setImageResource(ic_notifications); mNotifyStatusText.setText(R.string.notify_on_all_messages); } if (getSupportActionBar() != null) { diff --git a/src/main/java/de/pixart/messenger/ui/RecordingActivity.java b/src/main/java/de/pixart/messenger/ui/RecordingActivity.java index 21462ebfa..7ea474c75 100644 --- a/src/main/java/de/pixart/messenger/ui/RecordingActivity.java +++ b/src/main/java/de/pixart/messenger/ui/RecordingActivity.java @@ -8,7 +8,6 @@ import android.os.Build; import android.os.Bundle; import android.os.Handler; import android.os.SystemClock; -import android.support.v7.app.AppCompatActivity; import android.util.Log; import android.view.View; import android.view.WindowManager; @@ -25,7 +24,7 @@ import de.pixart.messenger.Config; import de.pixart.messenger.R; import de.pixart.messenger.persistance.FileBackend; -public class RecordingActivity extends AppCompatActivity implements View.OnClickListener { +public class RecordingActivity extends XmppActivity implements View.OnClickListener { private TextView mTimerTextView; private Button mCancelButton; @@ -51,6 +50,8 @@ public class RecordingActivity extends AppCompatActivity implements View.OnClick protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_recording); + this.mTheme = findTheme(); + setTheme(this.mTheme); this.mTimerTextView = this.findViewById(R.id.timer); this.mCancelButton = this.findViewById(R.id.cancel_button); this.mCancelButton.setOnClickListener(this); @@ -58,6 +59,12 @@ public class RecordingActivity extends AppCompatActivity implements View.OnClick this.mStopButton.setOnClickListener(this); this.setFinishOnTouchOutside(false); getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); + this.setTitle(R.string.attach_record_voice); + } + + @Override + protected void refreshUiReal() { + } @Override @@ -79,6 +86,11 @@ public class RecordingActivity extends AppCompatActivity implements View.OnClick } } + @Override + void onBackendConnected() { + + } + private boolean startRecording() { mRecorder = new MediaRecorder(); mRecorder.setAudioSource(MediaRecorder.AudioSource.MIC); @@ -162,4 +174,18 @@ public class RecordingActivity extends AppCompatActivity implements View.OnClick break; } } + + public boolean isDarkTheme() { + return this.mTheme == R.style.ConversationsDialog_Dark; + } + + protected int findTheme() { + Boolean dark = getPreferences().getString(SettingsActivity.THEME, getResources().getString(R.string.theme)).equals("dark"); + + if (dark) { + return R.style.ConversationsDialog_Dark; + } else { + return R.style.ConversationsDialog; + } + } } \ No newline at end of file diff --git a/src/main/java/de/pixart/messenger/ui/SettingsActivity.java b/src/main/java/de/pixart/messenger/ui/SettingsActivity.java index 48c5f46fd..190fc0c43 100644 --- a/src/main/java/de/pixart/messenger/ui/SettingsActivity.java +++ b/src/main/java/de/pixart/messenger/ui/SettingsActivity.java @@ -69,6 +69,8 @@ public class SettingsActivity extends XmppActivity implements @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); + this.mTheme = findTheme(); + setTheme(this.mTheme); setContentView(R.layout.activity_settings); FragmentManager fm = getFragmentManager(); mSettingsFragment = (SettingsFragment) fm.findFragmentById(R.id.settings_content); @@ -77,9 +79,7 @@ public class SettingsActivity extends XmppActivity implements fm.beginTransaction().replace(R.id.settings_content, mSettingsFragment).commit(); } mSettingsFragment.setActivityIntent(getIntent()); - this.mTheme = findTheme(); - setTheme(this.mTheme); - getWindow().getDecorView().setBackgroundColor(Color.get(this, R.attr.color_background_primary)); + getWindow().getDecorView().setBackgroundColor(Color.get(this, R.attr.color_background_secondary)); setSupportActionBar(findViewById(R.id.toolbar)); configureActionBar(getSupportActionBar()); } @@ -92,8 +92,9 @@ public class SettingsActivity extends XmppActivity implements @Override public void onStart() { super.onStart(); - PreferenceManager.getDefaultSharedPreferences(this).registerOnSharedPreferenceChangeListener(this); + updateTheme(); + PreferenceManager.getDefaultSharedPreferences(this).registerOnSharedPreferenceChangeListener(this); multiAccountPreference = mSettingsFragment.findPreference("enable_multi_accounts"); if (multiAccountPreference != null) { isMultiAccountChecked = ((CheckBoxPreference) multiAccountPreference).isChecked(); @@ -269,6 +270,13 @@ public class SettingsActivity extends XmppActivity implements } } + private void updateTheme() { + final int theme = findTheme(); + if (this.mTheme != theme) { + recreate(); + } + } + private void changeOmemoSettingSummary() { ListPreference omemoPreference = (ListPreference) mSettingsFragment.findPreference(OMEMO_SETTING); if (omemoPreference != null) { @@ -495,10 +503,7 @@ public class SettingsActivity extends XmppActivity implements } else if (name.equals(AUTOMATIC_MESSAGE_DELETION)) { xmppConnectionService.expireOldMessages(true); } else if (name.equals(THEME)) { - final int theme = findTheme(); - if (this.mTheme != theme) { - recreate(); - } + updateTheme(); } } diff --git a/src/main/java/de/pixart/messenger/ui/ShareLocationActivity.java b/src/main/java/de/pixart/messenger/ui/ShareLocationActivity.java index 9ad877db1..2620d91c6 100644 --- a/src/main/java/de/pixart/messenger/ui/ShareLocationActivity.java +++ b/src/main/java/de/pixart/messenger/ui/ShareLocationActivity.java @@ -188,11 +188,9 @@ public class ShareLocationActivity extends LocationActivity implements LocationL private void setShareButtonEnabled(final boolean enabled) { if (enabled) { this.mShareButton.setEnabled(true); - this.mShareButton.setTextColor(0xff2e4272); this.mShareButton.setText(R.string.share); } else { this.mShareButton.setEnabled(false); - this.mShareButton.setTextColor(0x8a000000); this.mShareButton.setText(R.string.locating); } } diff --git a/src/main/java/de/pixart/messenger/ui/XmppActivity.java b/src/main/java/de/pixart/messenger/ui/XmppActivity.java index a2e938e8f..a3ddb8a95 100644 --- a/src/main/java/de/pixart/messenger/ui/XmppActivity.java +++ b/src/main/java/de/pixart/messenger/ui/XmppActivity.java @@ -412,16 +412,20 @@ public abstract class XmppActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); + this.mTheme = findTheme(); + setTheme(this.mTheme); metrics = getResources().getDisplayMetrics(); ExceptionHelper.init(getApplicationContext()); this.isCameraFeatureAvailable = getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA); mColorRed = ContextCompat.getColor(this, R.color.red800); - mColorWarningButton = ContextCompat.getColor(this, R.color.warning_button); + if (isDarkTheme()) { + mColorWarningButton = ContextCompat.getColor(this, R.color.warning_button_dark); + } else { + mColorWarningButton = ContextCompat.getColor(this, R.color.warning_button); + } mColorWhite = ContextCompat.getColor(this, R.color.white70); mColorOrange = ContextCompat.getColor(this, R.color.orange500); mColorGreen = ContextCompat.getColor(this, R.color.realgreen); - this.mTheme = findTheme(); - setTheme(this.mTheme); this.mUsingEnterKey = usingEnterKey(); mUseSubject = getPreferences().getBoolean("use_subject", getResources().getBoolean(R.bool.use_subject)); } @@ -1011,10 +1015,9 @@ public abstract class XmppActivity extends AppCompatActivity { protected int findTheme() { Boolean dark = getPreferences().getString(SettingsActivity.THEME, getResources().getString(R.string.theme)).equals("dark"); - Boolean larger = getPreferences().getBoolean("use_larger_font", getResources().getBoolean(R.bool.use_larger_font)); - if (larger) { - return R.style.ConversationsTheme_LargerText; + if (dark) { + return R.style.ConversationsTheme_Dark; } else { return R.style.ConversationsTheme; } diff --git a/src/main/java/de/pixart/messenger/ui/adapter/ConversationAdapter.java b/src/main/java/de/pixart/messenger/ui/adapter/ConversationAdapter.java index 249aa9cb4..d6e875a94 100644 --- a/src/main/java/de/pixart/messenger/ui/adapter/ConversationAdapter.java +++ b/src/main/java/de/pixart/messenger/ui/adapter/ConversationAdapter.java @@ -246,11 +246,11 @@ public class ConversationAdapter extends ArrayAdapter { viewHolder.name.setTextColor(ContextCompat.getColor(activity, R.color.notavailable)); break; default: - viewHolder.name.setTextColor(ContextCompat.getColor(activity, R.color.black87)); + viewHolder.name.setTextColor(Color.get(activity, R.attr.text_Color_Main)); break; } } else { - viewHolder.name.setTextColor(ContextCompat.getColor(activity, R.color.black87)); + viewHolder.name.setTextColor(Color.get(activity, R.attr.text_Color_Main)); } if (activity.xmppConnectionService.indicateReceived()) { diff --git a/src/main/java/de/pixart/messenger/ui/adapter/ListItemAdapter.java b/src/main/java/de/pixart/messenger/ui/adapter/ListItemAdapter.java index 432bc0d4b..75d105484 100644 --- a/src/main/java/de/pixart/messenger/ui/adapter/ListItemAdapter.java +++ b/src/main/java/de/pixart/messenger/ui/adapter/ListItemAdapter.java @@ -8,7 +8,6 @@ import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.Drawable; import android.os.AsyncTask; import android.preference.PreferenceManager; -import android.support.v4.content.ContextCompat; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; @@ -27,6 +26,7 @@ import de.pixart.messenger.databinding.ContactBinding; import de.pixart.messenger.entities.ListItem; import de.pixart.messenger.ui.SettingsActivity; import de.pixart.messenger.ui.XmppActivity; +import de.pixart.messenger.ui.util.Color; import de.pixart.messenger.utils.IrregularUnicodeDetector; import de.pixart.messenger.utils.UIHelper; import rocks.xmpp.addr.Jid; @@ -104,7 +104,7 @@ public class ListItemAdapter extends ArrayAdapter { } } if (offline) { - viewHolder.name.setTextColor(ContextCompat.getColor(activity, R.color.black87)); + viewHolder.name.setTextColor(Color.get(activity, R.attr.text_Color_Main)); viewHolder.name.setAlpha(INACTIVE_ALPHA); viewHolder.jid.setAlpha(INACTIVE_ALPHA); viewHolder.avatar.setAlpha(INACTIVE_ALPHA); @@ -113,7 +113,7 @@ public class ListItemAdapter extends ArrayAdapter { if (ShowPresenceColoredNames()) { viewHolder.name.setTextColor(color); } else { - viewHolder.name.setTextColor(ContextCompat.getColor(activity, R.color.black87)); + viewHolder.name.setTextColor(Color.get(activity, R.attr.text_Color_Main)); } viewHolder.name.setAlpha(ACTIVE_ALPHA); viewHolder.jid.setAlpha(ACTIVE_ALPHA); diff --git a/src/main/java/de/pixart/messenger/ui/adapter/MessageAdapter.java b/src/main/java/de/pixart/messenger/ui/adapter/MessageAdapter.java index 6040017d6..3eba89ffe 100644 --- a/src/main/java/de/pixart/messenger/ui/adapter/MessageAdapter.java +++ b/src/main/java/de/pixart/messenger/ui/adapter/MessageAdapter.java @@ -152,7 +152,6 @@ public class MessageAdapter extends ArrayAdapter implements CopyTextVie private OnContactPictureClicked mOnContactPictureClickedListener; private OnContactPictureLongClicked mOnContactPictureLongClickedListener; private boolean mIndicateReceived = false; - private boolean mUseWhiteBackground = false; private OnQuoteListener onQuoteListener; public MessageAdapter(XmppActivity activity, List messages) { @@ -239,9 +238,9 @@ public class MessageAdapter extends ArrayAdapter implements CopyTextVie public int getMessageTextColor(boolean onDark, boolean primary) { if (onDark) { - return ContextCompat.getColor(activity, primary ? R.color.dark : R.color.primary); + return ContextCompat.getColor(activity, primary ? R.color.white : R.color.white70); } else { - return ContextCompat.getColor(activity, primary ? R.color.dark : R.color.primary); + return ContextCompat.getColor(activity, primary ? R.color.black87 : R.color.black54); } } @@ -257,7 +256,8 @@ public class MessageAdapter extends ArrayAdapter implements CopyTextVie if (viewHolder.edit_indicator != null) { if (message.edited()) { viewHolder.edit_indicator.setVisibility(View.VISIBLE); - viewHolder.edit_indicator.setAlpha(0.7f); + viewHolder.edit_indicator.setImageResource(darkBackground ? R.drawable.ic_mode_edit_white_18dp : R.drawable.ic_mode_edit_black_18dp); + viewHolder.edit_indicator.setAlpha(darkBackground ? 0.7f : 0.57f); } else { viewHolder.edit_indicator.setVisibility(View.GONE); } @@ -304,7 +304,8 @@ public class MessageAdapter extends ArrayAdapter implements CopyTextVie } break; case Message.STATUS_SEND_FAILED: - if (isResendable) { + DownloadableFile file = activity.xmppConnectionService.getFileBackend().getFile(message); + if (isResendable && file.exists()) { info = getContext().getString(R.string.send_failed_resend); } else { info = getContext().getString(R.string.send_failed); @@ -318,6 +319,7 @@ public class MessageAdapter extends ArrayAdapter implements CopyTextVie break; } if (error && type == SENT) { + viewHolder.time.setTextAppearance(getContext(), R.style.TextAppearance_Conversations_Caption_Waring); viewHolder.time.setTextAppearance(getContext(), R.style.TextAppearance_Conversations_Caption_Waring); DownloadableFile file = activity.xmppConnectionService.getFileBackend().getFile(message); if (file.exists()) { @@ -328,6 +330,9 @@ public class MessageAdapter extends ArrayAdapter implements CopyTextVie isResendable = false; viewHolder.resend_button.setVisibility(View.VISIBLE); } + } else { + isResendable = false; + viewHolder.resend_button.setVisibility(View.GONE); } viewHolder.resend_button.setText(R.string.send_again); viewHolder.resend_button.setCompoundDrawablesWithIntrinsicBounds(R.drawable.ic_resend_grey600_48dp, 0, 0, 0); @@ -341,6 +346,11 @@ public class MessageAdapter extends ArrayAdapter implements CopyTextVie }); } else if (!error && type == SENT) { viewHolder.resend_button.setVisibility(View.GONE); + if (darkBackground) { + viewHolder.time.setTextAppearance(getContext(), R.style.TextAppearance_Conversations_Caption_OnDark); + } else { + viewHolder.time.setTextAppearance(getContext(), R.style.TextAppearance_Conversations_Caption); + } viewHolder.time.setTextColor(this.getMessageTextColor(darkBackground, false)); } else { if (darkBackground) { @@ -363,11 +373,15 @@ public class MessageAdapter extends ArrayAdapter implements CopyTextVie } } if (verified) { - viewHolder.indicator.setImageResource(R.drawable.ic_verified_user_blue_18dp); + viewHolder.indicator.setImageResource(darkBackground ? R.drawable.ic_verified_user_white_18dp : R.drawable.ic_verified_user_black_18dp); } else { - viewHolder.indicator.setImageResource(R.drawable.ic_lock_blue_18dp); + viewHolder.indicator.setImageResource(darkBackground ? R.drawable.ic_lock_white_18dp : R.drawable.ic_lock_black_18dp); + } + if (darkBackground) { + viewHolder.indicator.setAlpha(0.7f); + } else { + viewHolder.indicator.setAlpha(0.57f); } - viewHolder.indicator.setAlpha(0.7f); viewHolder.indicator.setVisibility(View.VISIBLE); } @@ -426,11 +440,16 @@ public class MessageAdapter extends ArrayAdapter implements CopyTextVie viewHolder.messageBody.setTextIsSelectable(false); } - private void displayEmojiMessage(final ViewHolder viewHolder, final String body) { + private void displayEmojiMessage(final ViewHolder viewHolder, final String body, final boolean darkBackground) { viewHolder.download_button.setVisibility(View.GONE); viewHolder.audioPlayer.setVisibility(View.GONE); viewHolder.image.setVisibility(View.GONE); viewHolder.messageBody.setVisibility(View.VISIBLE); + if (darkBackground) { + viewHolder.messageBody.setTextAppearance(getContext(), R.style.TextAppearance_Conversations_Body1_OnDark); + } else { + viewHolder.messageBody.setTextAppearance(getContext(), R.style.TextAppearance_Conversations_Body1); + } Spannable span = new SpannableString(body); float size = Emoticons.isEmoji(body) ? 3.0f : 2.0f; span.setSpan(new RelativeSizeSpan(size), 0, body.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); @@ -869,7 +888,7 @@ public class MessageAdapter extends ArrayAdapter implements CopyTextVie } } - boolean darkBackground = false; // default: (type == SENT && (!isInValidSession || !mUseWhiteBackground)); + boolean darkBackground = type == SENT && !isInValidSession || activity.isDarkTheme(); if (type == DATE_SEPARATOR) { if (UIHelper.today(message.getTimeSent())) { @@ -959,13 +978,7 @@ public class MessageAdapter extends ArrayAdapter implements CopyTextVie } } else { displayInfoMessage(viewHolder, activity.getString(R.string.install_openkeychain), darkBackground); - viewHolder.message_box.setOnClickListener(new OnClickListener() { - - @Override - public void onClick(View v) { - activity.showInstallPgpDialog(); - } - }); + viewHolder.message_box.setOnClickListener(v -> activity.showInstallPgpDialog()); } } else if (message.getEncryption() == Message.ENCRYPTION_DECRYPTION_FAILED) { displayDecryptionFailed(viewHolder, darkBackground); @@ -973,7 +986,7 @@ public class MessageAdapter extends ArrayAdapter implements CopyTextVie if (message.isGeoUri()) { displayLocationMessage(viewHolder, message); } else if (message.bodyIsOnlyEmojis() && message.getType() != Message.TYPE_PRIVATE) { - displayEmojiMessage(viewHolder, message.getBody().trim()); + displayEmojiMessage(viewHolder, message.getBody().trim(), darkBackground); } else if (message.isXmppUri()) { displayXmppMessage(viewHolder, message.getBody().trim()); } else if (message.treatAsDownloadable()) { @@ -997,12 +1010,14 @@ public class MessageAdapter extends ArrayAdapter implements CopyTextVie if (type == RECEIVED) { if (isInValidSession) { - viewHolder.message_box.setBackgroundResource(R.drawable.message_bubble_received_white); + viewHolder.message_box.setBackgroundResource(R.drawable.message_bubble_received_light); viewHolder.encryption.setVisibility(View.GONE); } else { - viewHolder.message_box.setBackgroundResource(R.drawable.message_bubble_received_lightred); + viewHolder.message_box.setBackgroundResource(R.drawable.message_bubble_received_warning); viewHolder.encryption.setVisibility(View.VISIBLE); - viewHolder.encryption.setTextColor(activity.getWarningTextColor()); + if (!darkBackground) { + viewHolder.encryption.setTextColor(activity.getWarningTextColor()); + } if (omemoEncryption && !message.isTrusted()) { viewHolder.encryption.setText(R.string.not_trusted); } else { @@ -1012,11 +1027,7 @@ public class MessageAdapter extends ArrayAdapter implements CopyTextVie } if (type == SENT) { - if (mUseWhiteBackground) { - viewHolder.message_box.setBackgroundResource(R.drawable.message_bubble_sent_white); - } else { - viewHolder.message_box.setBackgroundResource(R.drawable.message_bubble_sent_lightblue); - } + viewHolder.message_box.setBackgroundResource(R.drawable.message_bubble_sent_blue); } displayStatus(viewHolder, message, type, darkBackground); @@ -1144,7 +1155,6 @@ public class MessageAdapter extends ArrayAdapter implements CopyTextVie public void updatePreferences() { SharedPreferences p = PreferenceManager.getDefaultSharedPreferences(activity); this.mIndicateReceived = p.getBoolean("indicate_received", activity.getResources().getBoolean(R.bool.indicate_received)); - this.mUseWhiteBackground = p.getBoolean("use_white_background", activity.getResources().getBoolean(R.bool.use_white_background)); } public void loadAvatar(Message message, ImageView imageView, int size) { -- cgit v1.2.3