]> Pileus Git - ~andy/freeotp/blob - src/org/fedorahosted/freeotp/TokenAdapter.java
Relicense to Apache 2.0
[~andy/freeotp] / src / org / fedorahosted / freeotp / TokenAdapter.java
1 /*
2  * FreeOTP
3  *
4  * Authors: Nathaniel McCallum <npmccallum@redhat.com>
5  *
6  * Copyright (C) 2013  Nathaniel McCallum, Red Hat
7  *
8  * Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  *
12  *     http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  */
20
21 package org.fedorahosted.freeotp;
22
23 import java.util.ArrayList;
24 import java.util.Collections;
25 import java.util.Comparator;
26 import java.util.HashMap;
27 import java.util.List;
28 import java.util.Map;
29
30 import org.fedorahosted.freeotp.Token.TokenUriInvalidException;
31
32 import android.app.AlertDialog;
33 import android.content.Context;
34 import android.content.DialogInterface;
35 import android.os.Handler;
36 import android.os.Message;
37 import android.view.View;
38 import android.view.View.OnClickListener;
39 import android.view.ViewGroup;
40 import android.widget.BaseAdapter;
41 import android.widget.ImageButton;
42 import android.widget.ProgressBar;
43 import android.widget.TextView;
44
45 public class TokenAdapter extends BaseAdapter {
46         private static class Ticker extends Handler {
47                 private static interface OnTickListener {
48                         public void tick(ProgressBar pb);
49                 }
50
51                 private final Map<ProgressBar, OnTickListener> map = new HashMap<ProgressBar, OnTickListener>();
52
53                 @Override
54                 public void handleMessage(Message msg) {
55                         for (ProgressBar pb : map.keySet())
56                                 map.get(pb).tick(pb);
57
58                         sendEmptyMessageDelayed(0, 200);
59                 }
60
61                 public void set(ProgressBar pb, OnTickListener otl) {
62                         map.put(pb, otl);
63                 }
64         }
65
66         private final List<Token> tokens = new ArrayList<Token>();
67         private final Ticker ticker = new Ticker();
68
69         private void sort() {
70                 Collections.sort(tokens, new Comparator<Token>() {
71                         @Override
72                         public int compare(Token lhs, Token rhs) {
73                                 return lhs.getTitle().compareTo(rhs.getTitle());
74                         }
75                 });
76         }
77
78         public TokenAdapter(Context ctx) {
79                 tokens.addAll(Token.getTokens(ctx));
80                 ticker.sendEmptyMessageDelayed(0, 200);
81                 sort();
82         }
83
84         @Override
85         public int getCount() {
86                 return tokens.size();
87         }
88
89         @Override
90         public Token getItem(int position) {
91                 return tokens.get(position);
92         }
93
94         @Override
95         public long getItemId(int position) {
96                 return position;
97         }
98
99         @Override
100         public View getView(int position, View convertView, ViewGroup parent) {
101                 final Context ctx = parent.getContext();
102
103                 if (convertView == null) {
104                         switch (getItem(position).getType()) {
105                         case HOTP:
106                                 convertView = View.inflate(ctx, R.layout.hotp, null);
107                                 break;
108
109                         case TOTP:
110                                 convertView = View.inflate(ctx, R.layout.totp, null);
111                                 break;
112                         }
113                 }
114
115                 final Token item = getItem(position);
116                 final TextView code = (TextView) convertView.findViewById(R.id.code);
117                 final TextView title = (TextView) convertView.findViewById(R.id.title);
118                 final ImageButton ib = (ImageButton) convertView.findViewById(R.id.button);
119
120                 code.setText(item.getCurrentTokenValue(ctx, false));
121                 title.setText(item.getTitle());
122
123                 ib.setOnClickListener(new OnClickListener() {
124                         @Override
125                         public void onClick(View v) {
126                                 String delmsg = ctx.getString(R.string.delete_message);
127
128                                 AlertDialog ad = new AlertDialog.Builder(ctx)
129                                 .setTitle("Delete")
130                                 .setMessage(delmsg + item.getTitle())
131                                 .setIcon(android.R.drawable.ic_delete)
132                                 .setPositiveButton(R.string.delete,
133                                                 new DialogInterface.OnClickListener() {
134                                                         @Override
135                                                         public void onClick(DialogInterface dialog, int which) {
136                                                                 tokens.remove(tokens.indexOf(item));
137                                                                 item.remove(ctx);
138                                                                 notifyDataSetChanged();
139                                                                 dialog.dismiss();
140                                                         }
141
142                                                 })
143                                 .setNegativeButton(android.R.string.cancel,
144                                                 new DialogInterface.OnClickListener() {
145                                                         @Override
146                                                         public void onClick(DialogInterface dialog, int which) {
147                                                                 dialog.cancel();
148                                                         }
149                                                 }).create();
150                                 ad.show();
151                         }
152                 });
153
154                 switch (getItem(position).getType()) {
155                 case HOTP:
156                         ImageButton hotp = (ImageButton) convertView.findViewById(R.id.hotpButton);
157                         hotp.setOnClickListener(new OnClickListener() {
158                                 @Override
159                                 public void onClick(View v) {
160                                         code.setText(item.getCurrentTokenValue(ctx, true));
161                                 }
162                         });
163                         break;
164
165                 case TOTP:
166                         ProgressBar pb = (ProgressBar) convertView.findViewById(R.id.totpProgressBar);
167                         ticker.set(pb, new Ticker.OnTickListener() {
168                                 @Override
169                                 public void tick(ProgressBar pb) {
170                                         int max = pb.getMax();
171                                         int pro = item.getProgress();
172                                         pb.setProgress(max - pro);
173                                         if (pro < max / 20 || pro > max / 20 * 19)
174                                                 code.setText(item.getCurrentTokenValue(ctx, false));
175                                 }
176                         });
177                         break;
178                 }
179
180                 return convertView;
181         }
182
183         @Override
184         public int getViewTypeCount() {
185                 return 2;
186         }
187
188         @Override
189         public int getItemViewType(int position) {
190                 switch (getItem(position).getType()) {
191                 case HOTP:
192                         return 0;
193                 case TOTP:
194                         return 1;
195                 default:
196                         return -1;
197                 }
198         }
199
200         public void add(Context ctx, String uri) throws TokenUriInvalidException {
201                 Token t = new Token(uri);
202                 t.save(ctx);
203                 tokens.add(t);
204                 sort();
205                 notifyDataSetChanged();
206         }
207 }