@@ -15,10 +15,15 @@ import android.support.v4.app.ActivityCompat
1515import  android.support.v4.content.ContextCompat 
1616import  android.support.v7.app.AppCompatActivity 
1717import  android.support.v7.app.AppCompatDelegate 
18+ import  android.support.v7.widget.DividerItemDecoration 
19+ import  android.support.v7.widget.LinearLayoutManager 
20+ import  android.support.v7.widget.RecyclerView 
1821import  android.text.Html 
1922import  android.util.Log 
23+ import  android.view.LayoutInflater 
2024import  android.view.Menu 
2125import  android.view.MenuItem 
26+ import  android.view.ViewGroup 
2227import  android.widget.* 
2328import  kotlinx.android.synthetic.main.activity_main.* 
2429import  net.glxn.qrgen.android.QRCode 
@@ -33,9 +38,10 @@ class MainActivity: AppCompatActivity() {
3338 //  This variable holds an ArrayList of WifiEntry objects that each contain a saved wifi SSID and
3439 //  password. It is updated whenever focus returns to the app (onResume).
3540 private  val  wifiEntries =  ArrayList <WifiEntry >()
36-  private  val  wifiEntrySSIDs  =  ArrayList < String >() 
41+  private  var  wifiList  =  wifiEntries 
3742 private  lateinit  var  loadWifiEntriesInBackgroundTask:  LoadWifiEntriesInBackground 
3843 private  lateinit  var  qrDialog:  AlertDialog 
44+  private  lateinit  var  searchView:  SearchView 
3945 private  lateinit  var  prefs:  SharedPreferences 
4046
4147 fun  sortWifiEntries (updateListView :  Boolean ) {
@@ -46,9 +52,89 @@ class MainActivity: AppCompatActivity() {
4652 }
4753 if  (! prefs.getBoolean(" sorting_order" DEFAULT_SORTING_ORDER )) wifiEntries.reverse()
4854 if  (updateListView) {
49-  wifiEntrySSIDs.clear()
50-  wifiEntries.mapTo(wifiEntrySSIDs) { it.title }
51-  (wifi_ListView.adapter as  ArrayAdapter <* >).notifyDataSetChanged()
55+  wifi_RecyclerView.adapter.notifyDataSetChanged()
56+  }
57+  }
58+ 59+  inner  class  WifiListAdapter : RecyclerView .Adapter <WifiListAdapter .ViewHolder >(), Filterable {
60+  inner  class  ViewHolder (val  item :  TextView ) : RecyclerView.ViewHolder(item) {
61+  lateinit  var  wifiEntry:  WifiEntry 
62+  init  {
63+  item.setOnClickListener {
64+  qrDialog =  AlertDialog .Builder (this @MainActivity).apply  {
65+  setView(ImageView (this @MainActivity).apply  {
66+  setPadding(0 , 0 , 0 , QR_CODE_DIALOG_BOTTOM_IMAGE_MARGIN )
67+  adjustViewBounds =  true 
68+  setImageBitmap(QRCode 
69+  .from(Wifi ()
70+  .withSsid(wifiEntry.title)
71+  .withPsk(wifiEntry.password)
72+  .withAuthentication(wifiEntry.type.asQRCodeAuth()))
73+  .withColor((if  (AppCompatDelegate .getDefaultNightMode() !=  AppCompatDelegate .MODE_NIGHT_YES ) 0xFF000000  else  0xFFE0E0E0 ).toInt(), 0x00000000 ) // TODO Better colour handling - atm, the colours may be wrong if the theme is set to system or auto.
74+  .withSize(prefs.getString(" qr_code_resolution" DEFAULT_QR_CODE_RESOLUTION ).toInt(), prefs.getString(" qr_code_resolution" DEFAULT_QR_CODE_RESOLUTION ).toInt())
75+  .bitmap())
76+  })
77+  setPositiveButton(" Done" ->  dialog.dismiss() }
78+  }.create()
79+  qrDialog.show()
80+  }
81+  item.setOnLongClickListener {
82+  qrDialog =  AlertDialog .Builder (this @MainActivity).apply  {
83+  setMessage(if  (Build .VERSION .SDK_INT  >=  Build .VERSION_CODES .N ) {
84+  Html .fromHtml(
85+  " <b>SSID:</b> ${wifiEntry.title ? :  " <i>ERROR</i>"  <br>" + 
86+  if  (wifiEntry.password !=  " " " <b>Password:</b> ${if  (wifiEntry.type !=  WifiEntry .Type .WEP ) wifiEntry.password else  wifiEntry.password.removePrefix(" \" " " \" "  <br>" else  { " " + 
87+  " <b>Type:</b> ${wifiEntry.type ? :  " </i>ERROR</i>"  " 
88+  Html .FROM_HTML_MODE_LEGACY )
89+  } else  {
90+  @Suppress(" DEPRECATION" 
91+  Html .fromHtml(
92+  " <b>SSID:</b> ${wifiEntry.title ? :  " <i>ERROR</i>"  <br>" + 
93+  if  (wifiEntry.password !=  " " " <b>Password:</b> ${if  (wifiEntry.type !=  WifiEntry .Type .WEP ) wifiEntry.password else  wifiEntry.password.removePrefix(" \" " " \" "  <br>" else  { " " + 
94+  " <b>Type:</b> ${wifiEntry.type ? :  " </i>ERROR</i>"  " 
95+  )
96+  }
97+  )
98+  setPositiveButton(" Done" ->  dialog.dismiss() }
99+  }.create()
100+  qrDialog.show()
101+  true 
102+  }
103+  }
104+  }
105+ 106+  override  fun  onCreateViewHolder (parent :  ViewGroup , viewType :  Int ) = 
107+  ViewHolder (LayoutInflater .from(parent.context).inflate(R .layout.wifi_list_item, parent, false ) as  TextView )
108+ 109+  override  fun  onBindViewHolder (holder :  ViewHolder , position :  Int ) {
110+  holder.wifiEntry =  wifiList[position]
111+  holder.item.text =  holder.wifiEntry.title
112+  }
113+ 114+  override  fun  getItemCount () =  wifiList.size
115+ 116+  override  fun  getFilter () =  object :  Filter () {
117+  override  fun  performFiltering (constraint :  CharSequence ): FilterResults  {
118+  return  FilterResults ().apply  {
119+  values =  ArrayList <WifiEntry >().apply  {
120+  wifiEntries.filterTo(this ) { it.title.contains(constraint, true ) }
121+  }
122+  }
123+  }
124+ 125+  override  fun  publishResults (constraint :  CharSequence , results :  FilterResults ) {
126+  wifiList =  if  (constraint ==  " " else  results.values as  ArrayList <WifiEntry >
127+  notifyDataSetChanged()
128+  }
129+ 130+  }
131+  }
132+ 133+  override  fun  onBackPressed () {
134+  if  (searchView.isIconified) {
135+  if  (Build .VERSION .SDK_INT  >=  Build .VERSION_CODES .LOLLIPOP ) finishAndRemoveTask() else  finish()
136+  } else  {
137+  searchView.isIconified =  true 
52138 }
53139 }
54140
@@ -67,48 +153,10 @@ class MainActivity: AppCompatActivity() {
67153 adview.adUnitId =  " a6acc0938ffd4af29f71abce19f035ec" 
68154 adview.loadAd()
69155
70-  wifi_ListView.adapter =  ArrayAdapter (this , android.R .layout.simple_list_item_1, wifiEntrySSIDs)
71-  wifi_ListView.setOnItemClickListener { _, view, _, _ -> 
72-  val  selectedWifiEntry =  wifiEntries.find {it.title ==  (view as  TextView ).text}
73-  qrDialog =  AlertDialog .Builder (this ).apply  {
74-  setView(ImageView (this @MainActivity).apply  {
75-  setPadding(0 , 0 , 0 , QR_CODE_DIALOG_BOTTOM_IMAGE_MARGIN )
76-  adjustViewBounds =  true 
77-  setImageBitmap(QRCode 
78-  .from(Wifi ()
79-  .withSsid(selectedWifiEntry!! .title)
80-  .withPsk(selectedWifiEntry.password)
81-  .withAuthentication(selectedWifiEntry.type.asQRCodeAuth()))
82-  .withColor((if  (AppCompatDelegate .getDefaultNightMode() !=  AppCompatDelegate .MODE_NIGHT_YES ) 0xFF000000  else  0xFFE0E0E0 ).toInt(), 0x00000000 ) // TODO Better colour handling - atm, the colours may be wrong if the theme is set to system or auto.
83-  .withSize(prefs.getString(" qr_code_resolution" DEFAULT_QR_CODE_RESOLUTION ).toInt(), prefs.getString(" qr_code_resolution" DEFAULT_QR_CODE_RESOLUTION ).toInt())
84-  .bitmap())
85-  })
86-  setPositiveButton(" Done" ->  dialog.dismiss() }
87-  }.create()
88-  qrDialog.show()
89-  }
90-  wifi_ListView.setOnItemLongClickListener { _, view, _, _ -> 
91-  val  selectedWifiEntry =  wifiEntries.find {it.title ==  (view as  TextView ).text}
92-  qrDialog =  AlertDialog .Builder (this ).apply  {
93-  setMessage(if  (Build .VERSION .SDK_INT  >=  Build .VERSION_CODES .N ) {
94-  Html .fromHtml(
95-  " <b>SSID:</b> ${selectedWifiEntry?.title ? :  " <i>ERROR</i>"  <br>" + 
96-  if  (selectedWifiEntry?.password ? :  " </i>ERROR</i>" !=  " " " <b>Password:</b> ${if  (selectedWifiEntry?.type ? :  WifiEntry .Type .NONE  !=  WifiEntry .Type .WEP ) selectedWifiEntry?.password ? :  " </i>ERROR</i>" else  selectedWifiEntry?.password?.removePrefix(" \" " " \" " ? :  " </i>ERROR</i>"  <br>" else  { " " + 
97-  " <b>Type:</b> ${selectedWifiEntry?.type ? :  " </i>ERROR</i>"  " 
98-  Html .FROM_HTML_MODE_LEGACY )
99-  } else  {
100-  @Suppress(" DEPRECATION" 
101-  Html .fromHtml(
102-  " <b>SSID:</b> ${selectedWifiEntry?.title ? :  " <i>ERROR</i>"  <br>" + 
103-  if  (selectedWifiEntry?.password ? :  " </i>ERROR</i>" !=  " " " <b>Password:</b> ${if  (selectedWifiEntry?.type ? :  WifiEntry .Type .NONE  !=  WifiEntry .Type .WEP ) selectedWifiEntry?.password ? :  " </i>ERROR</i>" else  selectedWifiEntry?.password?.removePrefix(" \" " " \" " ? :  " </i>ERROR</i>"  <br>" else  { " " + 
104-  " <b>Type:</b> ${selectedWifiEntry?.type ? :  " </i>ERROR</i>"  " 
105-  )
106-  }
107-  )
108-  setPositiveButton(" Done" ->  dialog.dismiss() }
109-  }.create()
110-  qrDialog.show()
111-  true 
156+  wifi_RecyclerView.apply  {
157+  layoutManager =  LinearLayoutManager (this @MainActivity)
158+  adapter =  WifiListAdapter ()
159+  addItemDecoration(DividerItemDecoration (context, DividerItemDecoration .VERTICAL ))
112160 }
113161 }
114162
@@ -154,12 +202,10 @@ class MainActivity: AppCompatActivity() {
154202 override  fun  doInBackground (vararg  params :  Unit? ) {
155203 loadWifiEntries()
156204 sortWifiEntries(false )
157-  wifiEntrySSIDs.clear()
158-  wifiEntries.mapTo(wifiEntrySSIDs) { it.title }
159205 }
160206
161207 override  fun  onPostExecute (result :  Unit? ) {
162-  (wifi_ListView .adapteras ArrayAdapter < * >) .notifyDataSetChanged()
208+  wifi_RecyclerView .adapter.notifyDataSetChanged()
163209 loadingDialog.dismiss()
164210 }
165211
@@ -206,6 +252,7 @@ class MainActivity: AppCompatActivity() {
206252 menuInflater.inflate(R .menu.menu_activity_main, menu)
207253
208254 (menu.findItem(R .id.app_bar_search).actionView as  SearchView ).apply  {
255+  searchView =  this 
209256 setSearchableInfo((getSystemService(Context .SEARCH_SERVICE ) as  SearchManager ).getSearchableInfo(componentName))
210257 setOnSearchClickListener {
211258 menu.findItem(R .id.sortItem).isVisible =  false 
@@ -214,12 +261,12 @@ class MainActivity: AppCompatActivity() {
214261 override  fun  onQueryTextSubmit (query :  String? ) =  false 
215262
216263 override  fun  onQueryTextChange (newText :  String ): Boolean  {
217-  (wifi_ListView .adapter as  ArrayAdapter < * > ).filter.filter(newText)
264+  (wifi_RecyclerView .adapter as  Filterable ).filter.filter(newText)
218265 return  true 
219266 }
220267 })
221268 setOnCloseListener {
222-  wifi_ListView.adapter  =  ArrayAdapter ( this @MainActivity, android. R .layout.simple_list_item_1, wifiEntrySSIDs) 
269+  wifiList  =  wifiEntries 
223270 menu.findItem(R .id.sortItem).isVisible =  true 
224271 invalidateOptionsMenu()
225272 false 
0 commit comments