Merge pull request #40 from finnmglas/feature/select-actions

Feature/select actions
This commit is contained in:
Finn M Glas 2020-05-29 18:11:42 +02:00 committed by GitHub
commit 83c7cad0db
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 222 additions and 403 deletions

View file

@ -60,7 +60,25 @@ class SettingsActivity : AppCompatActivity() {
fun backHome(view: View) { finish() }
/** Theme - related */
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
when (requestCode) {
REQUEST_CHOOSE_APP -> {
val value = data?.getStringExtra("value")
val forApp = data?.getStringExtra("forApp") ?: return
// Save the new App to Preferences
val sharedPref = this.getSharedPreferences(
getString(R.string.preference_file_key), Context.MODE_PRIVATE)
val editor : SharedPreferences.Editor = sharedPref.edit()
editor.putString("action_$forApp", value.toString())
editor.apply()
loadSettings(sharedPref)
}
else -> super.onActivityResult(requestCode, resultCode, data)
}
}
}

View file

@ -11,9 +11,11 @@ import android.view.View
import android.view.ViewGroup
import android.widget.Toast
import androidx.fragment.app.Fragment
import androidx.recyclerview.widget.LinearLayoutManager
import com.finnmglas.launcher.ChooseActivity
import com.finnmglas.launcher.R
import com.finnmglas.launcher.extern.*
import com.finnmglas.launcher.settings.actions.ActionsRecyclerAdapter
import kotlinx.android.synthetic.main.fragment_settings_apps.*
@ -27,7 +29,6 @@ class SettingsFragmentApps : Fragment() {
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
return inflater.inflate(R.layout.fragment_settings_apps, container, false)
}
@ -36,131 +37,22 @@ class SettingsFragmentApps : Fragment() {
if (getSavedTheme(context!!) == "custom") {
fragment_settings_apps_container.setBackgroundColor(dominantColor)
setButtonColor(fragment_settings_apps_choose_up_btn, vibrantColor)
setButtonColor(fragment_settings_apps_choose_down_btn, vibrantColor)
setButtonColor(fragment_settings_apps_choose_left_btn, vibrantColor)
setButtonColor(fragment_settings_apps_choose_right_btn, vibrantColor)
setButtonColor(fragment_settings_apps_choose_vol_up_btn, vibrantColor)
setButtonColor(fragment_settings_apps_choose_vol_down_btn, vibrantColor)
setButtonColor(fragment_settings_apps_choose_double_click_btn, vibrantColor)
setButtonColor(fragment_settings_apps_choose_long_click_btn, vibrantColor)
setButtonColor(fragment_settings_apps_btn, vibrantColor)
setButtonColor(fragment_settings_apps_install_btn, vibrantColor)
}
/* TODO: Simplify and put all this repetitive stuff in a loop */
if (upApp != "") {
val appIcon = context!!.packageManager.getApplicationIcon(upApp)
fragment_settings_apps_up_icon.setImageDrawable(appIcon)
// set up the list / recycler
val actionViewManager = LinearLayoutManager(context)
val actionViewAdapter = ActionsRecyclerAdapter( activity!! )
fragment_settings_apps_up_icon.visibility = View.VISIBLE
fragment_settings_apps_choose_up_btn.visibility = View.GONE
fragment_settings_apps_up_icon.setOnClickListener{ chooseApp("upApp") }
} else {
fragment_settings_apps_choose_up_btn.setOnClickListener{ chooseApp("upApp") }
activity_settings_actions_recycler_view.apply {
// improve performance (since content changes don't change the layout size)
setHasFixedSize(true)
layoutManager = actionViewManager
adapter = actionViewAdapter
}
if (upApp != "") {
val appIcon = context!!.packageManager.getApplicationIcon(upApp)
fragment_settings_apps_up_icon.setImageDrawable(appIcon)
fragment_settings_apps_up_icon.visibility = View.VISIBLE
fragment_settings_apps_choose_up_btn.visibility = View.GONE
fragment_settings_apps_up_icon.setOnClickListener{ chooseApp("upApp") }
} else {
fragment_settings_apps_choose_up_btn.setOnClickListener{ chooseApp("upApp") }
}
if (downApp != "") {
val appIcon = context!!.packageManager.getApplicationIcon(downApp)
fragment_settings_apps_down_icon.setImageDrawable(appIcon)
fragment_settings_apps_down_icon.visibility = View.VISIBLE
fragment_settings_apps_choose_down_btn.visibility = View.GONE
fragment_settings_apps_down_icon.setOnClickListener{ chooseApp("downApp") }
} else {
fragment_settings_apps_choose_down_btn.setOnClickListener{ chooseApp("downApp") }
}
if (leftApp != "") {
val appIcon = context!!.packageManager.getApplicationIcon(leftApp)
fragment_settings_apps_left_icon.setImageDrawable(appIcon)
fragment_settings_apps_left_icon.visibility = View.VISIBLE
fragment_settings_apps_choose_left_btn.visibility = View.GONE
fragment_settings_apps_left_icon.setOnClickListener{ chooseApp("leftApp") }
} else {
fragment_settings_apps_choose_left_btn.setOnClickListener{ chooseApp("leftApp") }
}
if (rightApp != "") {
val appIcon = context!!.packageManager.getApplicationIcon(rightApp)
fragment_settings_apps_right_icon.setImageDrawable(appIcon)
fragment_settings_apps_right_icon.visibility = View.VISIBLE
fragment_settings_apps_choose_right_btn.visibility = View.GONE
fragment_settings_apps_right_icon.setOnClickListener{ chooseApp("rightApp") }
} else {
fragment_settings_apps_choose_right_btn.setOnClickListener{ chooseApp("rightApp") }
}
if (volumeUpApp != "") {
val appIcon = context!!.packageManager.getApplicationIcon(volumeUpApp)
fragment_settings_apps_vol_up_icon.setImageDrawable(appIcon)
fragment_settings_apps_vol_up_icon.visibility = View.VISIBLE
fragment_settings_apps_choose_vol_up_btn.visibility = View.GONE
fragment_settings_apps_vol_up_icon.setOnClickListener{ chooseApp("volumeUpApp") }
} else {
fragment_settings_apps_choose_vol_up_btn.setOnClickListener{ chooseApp("volumeUpApp") }
}
if (volumeDownApp != "") {
val appIcon = context!!.packageManager.getApplicationIcon(volumeDownApp)
fragment_settings_apps_vol_down_icon.setImageDrawable(appIcon)
fragment_settings_apps_vol_down_icon.visibility = View.VISIBLE
fragment_settings_apps_choose_vol_down_btn.visibility = View.GONE
fragment_settings_apps_vol_down_icon.setOnClickListener{ chooseApp("volumeDownApp") }
} else {
fragment_settings_apps_choose_vol_down_btn.setOnClickListener{ chooseApp("volumeDownApp") }
}
if (doubleClickApp != "") {
val appIcon = context!!.packageManager.getApplicationIcon(doubleClickApp)
fragment_settings_apps_double_click_icon.setImageDrawable(appIcon)
fragment_settings_apps_double_click_icon.visibility = View.VISIBLE
fragment_settings_apps_choose_double_click_btn.visibility = View.GONE
fragment_settings_apps_double_click_icon.setOnClickListener{ chooseApp("doubleClickApp") }
} else {
fragment_settings_apps_choose_double_click_btn.setOnClickListener{ chooseApp("doubleClickApp") }
}
if (longClickApp != "") {
val appIcon = context!!.packageManager.getApplicationIcon(longClickApp)
fragment_settings_apps_long_click_icon.setImageDrawable(appIcon)
fragment_settings_apps_long_click_icon.visibility = View.VISIBLE
fragment_settings_apps_choose_long_click_btn.visibility = View.GONE
fragment_settings_apps_long_click_icon.setOnClickListener{ chooseApp("longClickApp") }
} else {
fragment_settings_apps_choose_long_click_btn.setOnClickListener{ chooseApp("longClickApp") }
}
/* TODO * End * */
// App management buttons
fragment_settings_apps_btn.setOnClickListener{
val intent = Intent(this.context, ChooseActivity::class.java)
@ -181,34 +73,4 @@ class SettingsFragmentApps : Fragment() {
super.onStart()
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
when (requestCode) {
REQUEST_CHOOSE_APP -> {
val value = data?.getStringExtra("value")
val forApp = data?.getStringExtra("forApp") ?: return
// Save the new App to Preferences
val sharedPref = this.context!!.getSharedPreferences(
getString(R.string.preference_file_key), Context.MODE_PRIVATE)
val editor : SharedPreferences.Editor = sharedPref.edit()
editor.putString("action_$forApp", value.toString())
editor.apply()
loadSettings(sharedPref)
}
else -> super.onActivityResult(requestCode, resultCode, data)
}
}
/** Extra functions */
private fun chooseApp(forAction: String) {
val intent = Intent(this.context, ChooseActivity::class.java)
intent.putExtra("action", "pick")
intent.putExtra("forApp", forAction) // for which action we choose the app
startActivityForResult(intent, REQUEST_CHOOSE_APP)
}
}

View file

@ -0,0 +1,7 @@
package com.finnmglas.launcher.settings.actions
class ActionInfo(actionText: CharSequence, actionName: CharSequence, content: CharSequence) {
var actionName: CharSequence? = actionName
var actionText: CharSequence? = actionText
var content: CharSequence? = content
}

View file

@ -0,0 +1,104 @@
package com.finnmglas.launcher.settings.actions
import android.app.Activity
import android.content.Context
import android.content.Intent
import android.content.SharedPreferences
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.Button
import android.widget.ImageView
import android.widget.TextView
import androidx.recyclerview.widget.RecyclerView
import com.finnmglas.launcher.ChooseActivity
import com.finnmglas.launcher.R
import com.finnmglas.launcher.extern.FontAwesome
import com.finnmglas.launcher.extern.*
import java.lang.Exception
class ActionsRecyclerAdapter(val activity: Activity):
RecyclerView.Adapter<ActionsRecyclerAdapter.ViewHolder>() {
private val actionsList: MutableList<ActionInfo>
inner class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView),
View.OnClickListener {
var textView: TextView = itemView.findViewById(R.id.row_action_name)
var img: ImageView = itemView.findViewById(R.id.row_app_icon) as ImageView
var chooseButton: Button = itemView.findViewById(R.id.row_choose_button)
var removeAction: FontAwesome = itemView.findViewById(R.id.row_remove_action)
override fun onClick(v: View) {
val pos = adapterPosition
val context: Context = v.context
val content = actionsList[pos]
}
init { itemView.setOnClickListener(this) }
}
override fun onBindViewHolder(viewHolder: ViewHolder, i: Int) {
val actionText = actionsList[i].actionText
val actionName = actionsList[i].actionName
val content = actionsList[i].content
viewHolder.textView.text = actionText
try {
viewHolder.img.setImageDrawable(activity.packageManager.getApplicationIcon(content.toString()))
viewHolder.img.setOnClickListener{ chooseApp(actionName.toString()) }
viewHolder.removeAction.setOnClickListener{
val sharedPref = activity.getSharedPreferences(
activity.getString(R.string.preference_file_key), Context.MODE_PRIVATE)
val editor : SharedPreferences.Editor = sharedPref.edit()
editor.putString("action_$actionName", "") // clear it
editor.apply()
viewHolder.img.visibility = View.INVISIBLE
viewHolder.removeAction.visibility = View.GONE
viewHolder.chooseButton.visibility = View.VISIBLE
viewHolder.chooseButton.setOnClickListener{ chooseApp(actionName.toString()) }
setButtonColor(viewHolder.chooseButton, vibrantColor)
}
} catch (e : Exception) {
viewHolder.img.visibility = View.INVISIBLE
viewHolder.removeAction.visibility = View.GONE
viewHolder.chooseButton.visibility = View.VISIBLE
viewHolder.chooseButton.setOnClickListener{ chooseApp(actionName.toString()) }
setButtonColor(viewHolder.chooseButton, vibrantColor)
}
}
override fun getItemCount(): Int { return actionsList.size }
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
val inflater = LayoutInflater.from(parent.context)
val view: View = inflater.inflate(R.layout.recycler_actions_row, parent, false)
return ViewHolder(view)
}
init {
actionsList = ArrayList()
actionsList.add(ActionInfo("Swipe Up","upApp", upApp))
actionsList.add(ActionInfo("Swipe Down","downApp", downApp))
actionsList.add(ActionInfo("Swipe Left", "leftApp", leftApp))
actionsList.add(ActionInfo("Swipe Right", "rightApp", rightApp))
actionsList.add(ActionInfo("Volume Up", "volumeUpApp", volumeUpApp))
actionsList.add(ActionInfo("Volume Down", "volumeDownApp", volumeDownApp))
actionsList.add(ActionInfo("Double Click", "doubleClickApp", doubleClickApp))
actionsList.add(ActionInfo("Long Click", "longClickApp", longClickApp))
}
/* */
private fun chooseApp(forAction: String) {
val intent = Intent(activity, ChooseActivity::class.java)
intent.putExtra("action", "pick")
intent.putExtra("forApp", forAction) // for which action we choose the app
activity.startActivityForResult(intent, REQUEST_CHOOSE_APP)
}
}

View file

@ -13,263 +13,31 @@
android:paddingRight="32sp"
tools:context=".settings.SettingsFragmentApps">
<TableLayout
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingBottom="32sp"
app:layout_constraintBottom_toBottomOf="parent"
android:layout_height="match_parent">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/activity_settings_actions_recycler_view"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_marginBottom="16dp"
app:layout_constraintBottom_toTopOf="@+id/settings_app_btn_layout"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<TableRow
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center_vertical"
android:minHeight="@dimen/app_action_height">
</androidx.recyclerview.widget.RecyclerView>
<TextView
android:id="@+id/fragment_settings_apps_text_up"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingLeft="10sp"
android:paddingRight="10sp"
android:text="@string/settings_choose_up"
android:textSize="20sp" />
<ImageView
android:id="@+id/fragment_settings_apps_up_icon"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:visibility="gone"
tools:ignore="ContentDescription" />
<Button
android:id="@+id/fragment_settings_apps_choose_up_btn"
<LinearLayout
android:id="@+id/settings_app_btn_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/settings_choose_btn"
android:textAllCaps="false"
android:visibility="visible" />
</TableRow>
<TableRow
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center_vertical"
android:minHeight="@dimen/app_action_height">
<TextView
android:id="@+id/fragment_settings_apps_choose_down_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingLeft="10sp"
android:paddingRight="10sp"
android:text="@string/settings_choose_down"
android:textSize="20sp" />
<ImageView
android:id="@+id/fragment_settings_apps_down_icon"
android:layout_width="wrap_content"
android:layout_height="@dimen/app_icon_side"
android:visibility="gone"
tools:ignore="ContentDescription" />
<Button
android:id="@+id/fragment_settings_apps_choose_down_btn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/settings_choose_btn"
android:textAllCaps="false" />
</TableRow>
<TableRow
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center_vertical"
android:minHeight="@dimen/app_action_height">
<TextView
android:id="@+id/fragment_settings_apps_choose_left_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingLeft="10sp"
android:paddingRight="10sp"
android:text="@string/settings_choose_left"
android:textSize="20sp" />
<ImageView
android:id="@+id/fragment_settings_apps_left_icon"
android:layout_width="wrap_content"
android:layout_height="@dimen/app_icon_side"
android:visibility="gone"
tools:ignore="ContentDescription" />
<Button
android:id="@+id/fragment_settings_apps_choose_left_btn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/settings_choose_btn"
android:textAllCaps="false" />
</TableRow>
<TableRow
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center_vertical"
android:minHeight="@dimen/app_action_height">
<TextView
android:id="@+id/fragment_settings_apps_choose_right_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingLeft="10sp"
android:paddingRight="10sp"
android:text="@string/settings_choose_right"
android:textSize="20sp" />
<ImageView
android:id="@+id/fragment_settings_apps_right_icon"
android:layout_width="wrap_content"
android:layout_height="@dimen/app_icon_side"
android:visibility="gone"
tools:ignore="ContentDescription" />
<Button
android:id="@+id/fragment_settings_apps_choose_right_btn"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/settings_choose_btn"
android:textAllCaps="false" />
</TableRow>
<TableRow
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center_vertical"
android:minHeight="@dimen/app_action_height">
<TextView
android:id="@+id/fragment_settings_apps_choose_vol_up_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingLeft="10sp"
android:paddingRight="10sp"
android:text="@string/settings_choose_vol_up"
android:textSize="20sp" />
<ImageView
android:id="@+id/fragment_settings_apps_vol_up_icon"
android:layout_width="wrap_content"
android:layout_height="@dimen/app_icon_side"
android:visibility="gone"
tools:ignore="ContentDescription" />
<Button
android:id="@+id/fragment_settings_apps_choose_vol_up_btn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/settings_choose_btn"
android:textAllCaps="false" />
</TableRow>
<TableRow
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center_vertical"
android:minHeight="@dimen/app_action_height">
<TextView
android:id="@+id/fragment_settings_apps_choose_vol_down_text"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingLeft="10sp"
android:paddingRight="10sp"
android:text="@string/settings_choose_vol_down"
android:textSize="20sp" />
<ImageView
android:id="@+id/fragment_settings_apps_vol_down_icon"
android:layout_width="wrap_content"
android:layout_height="@dimen/app_icon_side"
android:visibility="gone"
tools:ignore="ContentDescription" />
<Button
android:id="@+id/fragment_settings_apps_choose_vol_down_btn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/settings_choose_btn"
android:textAllCaps="false" />
</TableRow>
<TableRow
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center_vertical"
android:minHeight="@dimen/app_action_height">
<TextView
android:id="@+id/fragment_settings_apps_choose_double_click_text"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingLeft="10sp"
android:paddingRight="10sp"
android:text="@string/settings_choose_double_click"
android:textSize="20sp" />
<ImageView
android:id="@+id/fragment_settings_apps_double_click_icon"
android:layout_width="wrap_content"
android:layout_height="@dimen/app_icon_side"
android:visibility="gone"
tools:ignore="ContentDescription" />
<Button
android:id="@+id/fragment_settings_apps_choose_double_click_btn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/settings_choose_btn"
android:textAllCaps="false" />
</TableRow>
<TableRow
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center_vertical"
android:minHeight="@dimen/app_action_height">
<TextView
android:id="@+id/fragment_settings_apps_choose_long_click_text"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingLeft="10sp"
android:paddingRight="10sp"
android:text="@string/settings_choose_long_click"
android:textSize="20sp" />
<ImageView
android:id="@+id/fragment_settings_apps_long_click_icon"
android:layout_width="wrap_content"
android:layout_height="@dimen/app_icon_side"
android:visibility="gone"
tools:ignore="ContentDescription" />
<Button
android:id="@+id/fragment_settings_apps_choose_long_click_btn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/settings_choose_btn"
android:textAllCaps="false" />
</TableRow>
</TableLayout>
android:layout_marginBottom="32dp"
android:orientation="vertical"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent">
<Button
android:id="@+id/fragment_settings_apps_btn"
@ -286,3 +54,7 @@
android:textAllCaps="false" />
</LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
</LinearLayout>

View file

@ -0,0 +1,55 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:id="@+id/row_action_name"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginEnd="5dp"
android:layout_marginRight="5dp"
android:gravity="start"
android:text=""
android:textSize="20sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="@id/row_choose_button"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<Button
android:id="@+id/row_choose_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/settings_choose_btn"
android:textAllCaps="false"
android:visibility="invisible"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<ImageView
android:id="@+id/row_app_icon"
android:layout_width="@dimen/app_icon_side"
android:layout_height="@dimen/app_icon_side"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="@id/row_choose_button"
app:layout_constraintHorizontal_bias="0.2"
app:layout_constraintStart_toStartOf="@+id/row_choose_button"
app:layout_constraintTop_toTopOf="parent"
tools:ignore="ContentDescription" />
<com.finnmglas.launcher.extern.FontAwesome
android:id="@+id/row_remove_action"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="8sp"
android:text="@string/fas_times"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@+id/row_app_icon"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>

View file

@ -11,6 +11,7 @@
<string name="fas_donate" translatable="false">&#xf4b9;</string>
<string name="fas_share" translatable="false">&#xf064;</string>
<string name="fas_trash" translatable="false">&#xf1f8;</string>
<string name="fas_times" translatable="false">&#xf00d;</string>
<!-- icons that can be used with type="brands" -->
<string name="fab_apple" translatable="false">&#xf179;</string>