From 6d44717ef6ff2b133f650b0048c76c19219cab5b Mon Sep 17 00:00:00 2001 From: Corewala Date: Fri, 7 Jan 2022 16:26:18 -0500 Subject: [PATCH] Removed large gemtext --- .../java/corewala/buran/ui/GemActivity.kt | 30 +-- .../AbstractGemtextAdapter.kt | 14 +- .../GemtextAdapter.kt} | 7 +- .../GmiViewHolder.kt | 2 +- .../gemtext_adapters/LargeGemtextAdapter.kt | 253 ------------------ .../buran/ui/settings/SettingsFragment.kt | 6 - .../main/res/layout/gemtext_code_block.xml | 2 +- ...mage_link.xml => gemtext_image_button.xml} | 2 +- .../res/layout/gemtext_large_code_block.xml | 58 ---- app/src/main/res/layout/gemtext_large_h1.xml | 13 - app/src/main/res/layout/gemtext_large_h2.xml | 13 - app/src/main/res/layout/gemtext_large_h3.xml | 13 - .../main/res/layout/gemtext_large_quote.xml | 18 -- .../main/res/layout/gemtext_large_text.xml | 12 - ...large_link.xml => gemtext_link_button.xml} | 2 +- app/src/main/res/values-fr/strings.xml | 1 - app/src/main/res/values/dimens.xml | 11 +- app/src/main/res/values/strings.xml | 1 - 18 files changed, 17 insertions(+), 441 deletions(-) rename app/src/main/java/corewala/buran/ui/{gemtext_adapters => gemtext_adapter}/AbstractGemtextAdapter.kt (58%) rename app/src/main/java/corewala/buran/ui/{gemtext_adapters/DefaultGemtextAdapter.kt => gemtext_adapter/GemtextAdapter.kt} (98%) rename app/src/main/java/corewala/buran/ui/{gemtext_adapters => gemtext_adapter}/GmiViewHolder.kt (93%) delete mode 100644 app/src/main/java/corewala/buran/ui/gemtext_adapters/LargeGemtextAdapter.kt rename app/src/main/res/layout/{gemtext_large_image_link.xml => gemtext_image_button.xml} (95%) delete mode 100644 app/src/main/res/layout/gemtext_large_code_block.xml delete mode 100644 app/src/main/res/layout/gemtext_large_h1.xml delete mode 100644 app/src/main/res/layout/gemtext_large_h2.xml delete mode 100644 app/src/main/res/layout/gemtext_large_h3.xml delete mode 100644 app/src/main/res/layout/gemtext_large_quote.xml delete mode 100644 app/src/main/res/layout/gemtext_large_text.xml rename app/src/main/res/layout/{gemtext_large_link.xml => gemtext_link_button.xml} (93%) diff --git a/app/src/main/java/corewala/buran/ui/GemActivity.kt b/app/src/main/java/corewala/buran/ui/GemActivity.kt index 6be4b40..12f46f7 100644 --- a/app/src/main/java/corewala/buran/ui/GemActivity.kt +++ b/app/src/main/java/corewala/buran/ui/GemActivity.kt @@ -33,7 +33,7 @@ import corewala.buran.ui.bookmarks.BookmarkDialog import corewala.buran.ui.bookmarks.BookmarksDialog import corewala.buran.ui.content_image.ImageDialog import corewala.buran.ui.content_text.TextDialog -import corewala.buran.ui.gemtext_adapters.* +import corewala.buran.ui.gemtext_adapter.* import corewala.buran.ui.modals_menus.about.AboutDialog import corewala.buran.ui.modals_menus.history.HistoryDialog import corewala.buran.ui.modals_menus.input.InputDialog @@ -117,10 +117,7 @@ class GemActivity : AppCompatActivity() { prefs = PreferenceManager.getDefaultSharedPreferences(this) - adapter = when { - prefs.getBoolean("use_large_gemtext_adapter", false) -> AbstractGemtextAdapter.getLargeGmi(onLink) - else -> AbstractGemtextAdapter.getDefault(onLink) - } + adapter = AbstractGemtextAdapter.getAdapter(onLink) binding.gemtextRecycler.adapter = adapter @@ -268,25 +265,10 @@ class GemActivity : AppCompatActivity() { else -> hideClientCertShield() } - val useLargeGmiAdapter = prefs.getBoolean("use_large_gemtext_adapter", false) - when { - useLargeGmiAdapter -> { - if(adapter.typeId != GEMTEXT_ADAPTER_LARGE){ - gemtext_recycler.adapter = null - adapter = AbstractGemtextAdapter.getLargeGmi(onLink) - gemtext_recycler.adapter = adapter - refresh() - } - } - else -> { - if(adapter.typeId != GEMTEXT_ADAPTER_DEFAULT) { - gemtext_recycler.adapter = null - adapter = AbstractGemtextAdapter.getDefault(onLink) - gemtext_recycler.adapter = adapter - refresh() - } - } - } + gemtext_recycler.adapter = null + adapter = AbstractGemtextAdapter.getAdapter(onLink) + gemtext_recycler.adapter = adapter + refresh() val hideCodeBlocks = prefs.getBoolean( "collapse_code_blocks", diff --git a/app/src/main/java/corewala/buran/ui/gemtext_adapters/AbstractGemtextAdapter.kt b/app/src/main/java/corewala/buran/ui/gemtext_adapter/AbstractGemtextAdapter.kt similarity index 58% rename from app/src/main/java/corewala/buran/ui/gemtext_adapters/AbstractGemtextAdapter.kt rename to app/src/main/java/corewala/buran/ui/gemtext_adapter/AbstractGemtextAdapter.kt index fef7c99..45542dc 100644 --- a/app/src/main/java/corewala/buran/ui/gemtext_adapters/AbstractGemtextAdapter.kt +++ b/app/src/main/java/corewala/buran/ui/gemtext_adapter/AbstractGemtextAdapter.kt @@ -1,14 +1,10 @@ -package corewala.buran.ui.gemtext_adapters +package corewala.buran.ui.gemtext_adapter import android.net.Uri import androidx.recyclerview.widget.RecyclerView import java.net.URI -const val GEMTEXT_ADAPTER_DEFAULT = 0 -const val GEMTEXT_ADAPTER_LARGE = 1 - abstract class AbstractGemtextAdapter( - val typeId: Int, val onLink: (link: URI, longTap: Boolean, adapterPosition: Int) -> Unit ): RecyclerView.Adapter() { @@ -23,12 +19,8 @@ abstract class AbstractGemtextAdapter( abstract fun inferTitle(): String? companion object{ - fun getDefault(onLink: (link: URI, longTap: Boolean, adapterPosition: Int) -> Unit): AbstractGemtextAdapter { - return DefaultGemtextAdapter(GEMTEXT_ADAPTER_DEFAULT, onLink) - } - - fun getLargeGmi(onLink: (link: URI, longTap: Boolean, adapterPosition: Int) -> Unit): AbstractGemtextAdapter { - return LargeGemtextAdapter(GEMTEXT_ADAPTER_LARGE, onLink) + fun getAdapter(onLink: (link: URI, longTap: Boolean, adapterPosition: Int) -> Unit): AbstractGemtextAdapter { + return GemtextAdapter(onLink) } } } \ No newline at end of file diff --git a/app/src/main/java/corewala/buran/ui/gemtext_adapters/DefaultGemtextAdapter.kt b/app/src/main/java/corewala/buran/ui/gemtext_adapter/GemtextAdapter.kt similarity index 98% rename from app/src/main/java/corewala/buran/ui/gemtext_adapters/DefaultGemtextAdapter.kt rename to app/src/main/java/corewala/buran/ui/gemtext_adapter/GemtextAdapter.kt index 748786e..00cab54 100644 --- a/app/src/main/java/corewala/buran/ui/gemtext_adapters/DefaultGemtextAdapter.kt +++ b/app/src/main/java/corewala/buran/ui/gemtext_adapter/GemtextAdapter.kt @@ -1,4 +1,4 @@ -package corewala.buran.ui.gemtext_adapters +package corewala.buran.ui.gemtext_adapter import android.annotation.SuppressLint import android.net.Uri @@ -15,10 +15,9 @@ import corewala.endsWithImage import corewala.visible import java.net.URI -class DefaultGemtextAdapter( - typeId: Int, +class GemtextAdapter( onLink: (link: URI, longTap: Boolean, adapterPosition: Int) -> Unit) - : AbstractGemtextAdapter(typeId, onLink) { + : AbstractGemtextAdapter(onLink) { private var lines = mutableListOf() private var inlineImages = HashMap() diff --git a/app/src/main/java/corewala/buran/ui/gemtext_adapters/GmiViewHolder.kt b/app/src/main/java/corewala/buran/ui/gemtext_adapter/GmiViewHolder.kt similarity index 93% rename from app/src/main/java/corewala/buran/ui/gemtext_adapters/GmiViewHolder.kt rename to app/src/main/java/corewala/buran/ui/gemtext_adapter/GmiViewHolder.kt index 68764c7..f78dc81 100644 --- a/app/src/main/java/corewala/buran/ui/gemtext_adapters/GmiViewHolder.kt +++ b/app/src/main/java/corewala/buran/ui/gemtext_adapter/GmiViewHolder.kt @@ -1,4 +1,4 @@ -package corewala.buran.ui.gemtext_adapters +package corewala.buran.ui.gemtext_adapter import android.view.View import androidx.recyclerview.widget.RecyclerView diff --git a/app/src/main/java/corewala/buran/ui/gemtext_adapters/LargeGemtextAdapter.kt b/app/src/main/java/corewala/buran/ui/gemtext_adapters/LargeGemtextAdapter.kt deleted file mode 100644 index 528985e..0000000 --- a/app/src/main/java/corewala/buran/ui/gemtext_adapters/LargeGemtextAdapter.kt +++ /dev/null @@ -1,253 +0,0 @@ -package corewala.buran.ui.gemtext_adapters - -import android.annotation.SuppressLint -import android.net.Uri -import android.view.LayoutInflater -import android.view.View -import android.view.ViewGroup -import androidx.core.view.isVisible -import kotlinx.android.synthetic.main.gemtext_large_code_block.view.* -import kotlinx.android.synthetic.main.gemtext_large_image_link.view.* -import kotlinx.android.synthetic.main.gemtext_large_link.view.gemtext_text_link -import kotlinx.android.synthetic.main.gemtext_large_text.view.* -import corewala.buran.R -import corewala.endsWithImage -import corewala.visible -import java.net.URI - -class LargeGemtextAdapter( - typeId: Int, - onLink: (link: URI, longTap: Boolean, adapterPosition: Int) -> Unit) - : AbstractGemtextAdapter(typeId, onLink) { - - private var lines = mutableListOf() - private var inlineImages = HashMap() - - private val typeText = 0 - private val typeH1 = 1 - private val typeH2 = 2 - private val typeH3 = 3 - private val typeListItem = 4 - private val typeImageLink = 5 - private val typeLink = 6 - private val typeCodeBlock = 7 - private val typeQuote = 8 - - override fun render(lines: List){ - this.inlineImages.clear() - this.lines.clear() - this.lines.addAll(lines) - notifyDataSetChanged() - } - - private fun inflate(parent: ViewGroup, layout: Int): View{ - return LayoutInflater.from(parent.context).inflate(layout, parent, false) - } - - override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): GmiViewHolder { - return when(viewType){ - typeText -> GmiViewHolder.Text(inflate(parent, R.layout.gemtext_large_text)) - typeH1 -> GmiViewHolder.H1(inflate(parent, R.layout.gemtext_large_h1)) - typeH2 -> GmiViewHolder.H2(inflate(parent, R.layout.gemtext_large_h2)) - typeH3 -> GmiViewHolder.H3(inflate(parent, R.layout.gemtext_large_h3)) - typeListItem -> GmiViewHolder.ListItem(inflate(parent, R.layout.gemtext_large_text)) - typeImageLink -> GmiViewHolder.ImageLink(inflate(parent, R.layout.gemtext_large_image_link)) - typeLink -> GmiViewHolder.Link(inflate(parent, R.layout.gemtext_large_link)) - typeCodeBlock-> GmiViewHolder.Code(inflate(parent, R.layout.gemtext_large_code_block)) - typeQuote -> GmiViewHolder.Quote(inflate(parent, R.layout.gemtext_large_quote)) - else -> GmiViewHolder.Text(inflate(parent, R.layout.gemtext_large_text)) - } - } - - override fun getItemViewType(position: Int): Int { - val line = lines[position] - return when { - line.startsWith("```") -> typeCodeBlock - line.startsWith("###") -> typeH3 - line.startsWith("##") -> typeH2 - line.startsWith("#") -> typeH1 - line.startsWith("*") -> typeListItem - line.startsWith("=>") && getLink(line).endsWithImage() -> typeImageLink - line.startsWith("=>") -> typeLink - line.startsWith(">") -> typeQuote - else -> typeText - } - } - - override fun getItemCount(): Int = lines.size - - @SuppressLint("SetTextI18n") - override fun onBindViewHolder(holder: GmiViewHolder, position: Int) { - val line = lines[position] - - when(holder){ - is GmiViewHolder.Text -> holder.itemView.gemtext_text_textview.text = line - is GmiViewHolder.Code -> { - - var altText: String? = null - - if(line.startsWith("```<|ALT|>")){ - //there's alt text: "```<|ALT|>$alt" - altText = line.substring(10, line.indexOf("")) - holder.itemView.gemtext_text_monospace_textview.text = line.substring(line.indexOf("") + 7) - }else{ - holder.itemView.gemtext_text_monospace_textview.text = line.substring(3) - } - - if(hideCodeBlocks){ - holder.itemView.show_code_block.setText(R.string.show_code)//reset for recycling - altText?.let{ - holder.itemView.show_code_block.append(": $altText") - } - holder.itemView.show_code_block.visible(true) - holder.itemView.show_code_block.setOnClickListener { - setupCodeBlockToggle(holder, altText) - } - holder.itemView.gemtext_text_monospace_textview.visible(false) - - when { - showInlineIcons -> holder.itemView.show_code_block.setCompoundDrawablesRelativeWithIntrinsicBounds(0, 0, R.drawable.vector_code, 0) - else -> holder.itemView.show_code_block.setCompoundDrawablesRelativeWithIntrinsicBounds(0, 0, 0, 0) - } - }else{ - holder.itemView.show_code_block.visible(false) - holder.itemView.gemtext_text_monospace_textview.visible(true) - } - } - is GmiViewHolder.Quote -> holder.itemView.gemtext_text_monospace_textview.text = line.substring(1).trim() - is GmiViewHolder.H1 -> { - when { - line.length > 2 -> holder.itemView.gemtext_text_textview.text = line.substring(2).trim() - else -> holder.itemView.gemtext_text_textview.text = "" - } - } - is GmiViewHolder.H2 -> { - when { - line.length > 3 -> holder.itemView.gemtext_text_textview.text = line.substring(3).trim() - else -> holder.itemView.gemtext_text_textview.text = "" - } - } - is GmiViewHolder.H3 -> { - when { - line.length > 4 -> holder.itemView.gemtext_text_textview.text = line.substring(4).trim() - else -> holder.itemView.gemtext_text_textview.text = "" - } - } - is GmiViewHolder.ListItem -> holder.itemView.gemtext_text_textview.text = "• ${line.substring(1)}".trim() - is GmiViewHolder.Link -> { - val linkParts = line.substring(2).trim().split("\\s+".toRegex(), 2) - var linkName = linkParts[0] - - if(linkParts.size > 1) linkName = linkParts[1] - - val displayText = linkName - holder.itemView.gemtext_text_link.text = displayText - - when { - showInlineIcons && linkParts.first().startsWith("http") -> holder.itemView.gemtext_text_link.setCompoundDrawablesRelativeWithIntrinsicBounds(0, 0, R.drawable.vector_open_browser, 0) - else -> holder.itemView.gemtext_text_link.setCompoundDrawablesRelativeWithIntrinsicBounds(0, 0, 0, 0) - } - - holder.itemView.gemtext_text_link.setOnClickListener { - val uri = getUri(lines[holder.adapterPosition]) - println("User clicked link: $uri") - onLink(uri, false, holder.adapterPosition) - - } - holder.itemView.gemtext_text_link.setOnLongClickListener { - val uri = getUri(lines[holder.adapterPosition]) - println("User long-clicked link: $uri") - onLink(uri, true, holder.adapterPosition) - true - } - } - is GmiViewHolder.ImageLink -> { - val linkParts = line.substring(2).trim().split("\\s+".toRegex(), 2) - var linkName = linkParts[0] - - if(linkParts.size > 1) linkName = linkParts[1] - - val displayText = linkName - holder.itemView.gemtext_text_link.text = displayText - holder.itemView.gemtext_text_link.setOnClickListener { - val uri = getUri(lines[holder.adapterPosition]) - println("User clicked link: $uri") - onLink(uri, false, holder.adapterPosition) - - } - holder.itemView.gemtext_text_link.setOnLongClickListener { - val uri = getUri(lines[holder.adapterPosition]) - println("User long-clicked link: $uri") - onLink(uri, true, holder.adapterPosition) - true - } - - when { - inlineImages.containsKey(position) -> { - holder.itemView.gemtext_inline_image.visible(true) - holder.itemView.gemtext_inline_image.setImageURI(inlineImages[position]) - } - else -> holder.itemView.gemtext_inline_image.visible(false) - } - - when { - showInlineIcons -> holder.itemView.gemtext_text_link.setCompoundDrawablesWithIntrinsicBounds(0, 0, R.drawable.vector_photo, 0) - else -> holder.itemView.gemtext_text_link.setCompoundDrawablesWithIntrinsicBounds(0, 0, 0, 0) - } - } - } - } - - private fun setupCodeBlockToggle(holder: GmiViewHolder.Code, altText: String?) { - //val adapterPosition = holder.adapterPosition - when { - holder.itemView.gemtext_text_monospace_textview.isVisible -> { - holder.itemView.show_code_block.setText(R.string.show_code) - holder.itemView.gemtext_text_monospace_textview.visible(false) - altText?.let{ - holder.itemView.show_code_block.append(": $altText") - } - } - else -> { - holder.itemView.show_code_block.setText(R.string.hide_code) - holder.itemView.gemtext_text_monospace_textview.visible(true) - altText?.let{ - holder.itemView.show_code_block.append(": $altText") - } - } - } - } - - private fun getLink(line: String): String{ - val linkParts = line.substring(2).trim().split("\\s+".toRegex(), 2) - return linkParts[0] - } - - private fun getUri(linkLine: String): URI{ - val linkParts = linkLine.substring(2).trim().split("\\s+".toRegex(), 2) - return URI.create(linkParts.first()) - } - - override fun inferTitle(): String? { - lines.forEach { line -> - if(line.startsWith("#")) return line.replace("#", "").trim() - } - - return null - } - - override fun loadImage(position: Int, cacheUri: Uri){ - inlineImages[position] = cacheUri - notifyItemChanged(position) - } - - override fun inlineIcons(visible: Boolean){ - this.showInlineIcons = visible - notifyDataSetChanged() - } - - override fun hideCodeBlocks(hideCodeBlocks: Boolean) { - this.hideCodeBlocks = hideCodeBlocks - notifyDataSetChanged() - } -} \ No newline at end of file diff --git a/app/src/main/java/corewala/buran/ui/settings/SettingsFragment.kt b/app/src/main/java/corewala/buran/ui/settings/SettingsFragment.kt index 95ea74c..d78e135 100644 --- a/app/src/main/java/corewala/buran/ui/settings/SettingsFragment.kt +++ b/app/src/main/java/corewala/buran/ui/settings/SettingsFragment.kt @@ -185,12 +185,6 @@ class SettingsFragment: PreferenceFragmentCompat(), Preference.OnPreferenceChang collapseCodeBlocksPreference.title = getString(R.string.collapse_code_blocks) accessibilityCategory.addPreference(collapseCodeBlocksPreference) - //Accessibility - large text and buttons - val largeGemtextPreference = SwitchPreferenceCompat(context) - largeGemtextPreference.key = "use_large_gemtext_adapter" - largeGemtextPreference.title = getString(R.string.large_gemtext_and_button) - accessibilityCategory.addPreference(largeGemtextPreference) - //Accessibility - inline icons val showInlineIconsPreference = SwitchPreferenceCompat(context) showInlineIconsPreference.setDefaultValue(true) diff --git a/app/src/main/res/layout/gemtext_code_block.xml b/app/src/main/res/layout/gemtext_code_block.xml index f56f05f..6897f61 100644 --- a/app/src/main/res/layout/gemtext_code_block.xml +++ b/app/src/main/res/layout/gemtext_code_block.xml @@ -12,7 +12,7 @@ - - - - - - - - - \ No newline at end of file diff --git a/app/src/main/res/layout/gemtext_large_h1.xml b/app/src/main/res/layout/gemtext_large_h1.xml deleted file mode 100644 index 03f513a..0000000 --- a/app/src/main/res/layout/gemtext_large_h1.xml +++ /dev/null @@ -1,13 +0,0 @@ - - \ No newline at end of file diff --git a/app/src/main/res/layout/gemtext_large_h2.xml b/app/src/main/res/layout/gemtext_large_h2.xml deleted file mode 100644 index 917b3b1..0000000 --- a/app/src/main/res/layout/gemtext_large_h2.xml +++ /dev/null @@ -1,13 +0,0 @@ - - \ No newline at end of file diff --git a/app/src/main/res/layout/gemtext_large_h3.xml b/app/src/main/res/layout/gemtext_large_h3.xml deleted file mode 100644 index 1e60655..0000000 --- a/app/src/main/res/layout/gemtext_large_h3.xml +++ /dev/null @@ -1,13 +0,0 @@ - - \ No newline at end of file diff --git a/app/src/main/res/layout/gemtext_large_quote.xml b/app/src/main/res/layout/gemtext_large_quote.xml deleted file mode 100644 index 72ac4c3..0000000 --- a/app/src/main/res/layout/gemtext_large_quote.xml +++ /dev/null @@ -1,18 +0,0 @@ - - \ No newline at end of file diff --git a/app/src/main/res/layout/gemtext_large_text.xml b/app/src/main/res/layout/gemtext_large_text.xml deleted file mode 100644 index ab06559..0000000 --- a/app/src/main/res/layout/gemtext_large_text.xml +++ /dev/null @@ -1,12 +0,0 @@ - - \ No newline at end of file diff --git a/app/src/main/res/layout/gemtext_large_link.xml b/app/src/main/res/layout/gemtext_link_button.xml similarity index 93% rename from app/src/main/res/layout/gemtext_large_link.xml rename to app/src/main/res/layout/gemtext_link_button.xml index bfdbadb..c960c06 100644 --- a/app/src/main/res/layout/gemtext_large_link.xml +++ b/app/src/main/res/layout/gemtext_link_button.xml @@ -12,7 +12,7 @@ android:layout_marginRight="@dimen/screen_margin" android:layout_marginTop="@dimen/default_margin_small" android:layout_marginBottom="@dimen/default_margin_small" - android:textSize="@dimen/large_text_size" + android:textSize="@dimen/default_text_size" android:clickable="true" android:focusable="true" android:textAllCaps="false" diff --git a/app/src/main/res/values-fr/strings.xml b/app/src/main/res/values-fr/strings.xml index fcfbe4b..d3f3854 100644 --- a/app/src/main/res/values-fr/strings.xml +++ b/app/src/main/res/values-fr/strings.xml @@ -72,7 +72,6 @@ Cacher les rectangles pleins Montrer le code Cacher le code - Gemtexte large Les capsules Gemini utilisent malheureusement souvent des en-têtes en ascii-art rendus avec des rectangles pleins à largeur fixe. Quand les rectangles pleins sont cachés, ils nécessitent un clic pour être affichés, ce qui améliore l\'ergonomie en cas d\'utilisation d\'un lecteur d\'écran. Utiliser une couleur d\'arrière-plan personnalisée Couleur d\'arrière-plan diff --git a/app/src/main/res/values/dimens.xml b/app/src/main/res/values/dimens.xml index d1338cd..fb4ed0e 100644 --- a/app/src/main/res/values/dimens.xml +++ b/app/src/main/res/values/dimens.xml @@ -7,7 +7,7 @@ 20dp 12dp - + 16sp 20sp 14sp @@ -15,15 +15,6 @@ 26sp 22sp - - 22sp - 28sp - 18sp - 40sp - 34sp - 30sp - - 32dp 50dp 20dp diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index a488877..11063e3 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -72,7 +72,6 @@ Hide code blocks Show code Hide code - Large Gemtext Gemini capsules unfortunately often use ascii-art headers rendered in monospaced code blocks. When code blocks are hidden they require a tap to expand which improves usability when using a screen reader. Use custom page background colour Page Background Colour