use of com.ichi2.anki.R in project Anki-Android by ankidroid.
the class NoteEditorTest method stickyFieldsAreUnchangedAfterAdd.
@Test
public void stickyFieldsAreUnchangedAfterAdd() {
// #6795 - newlines were converted to <br>
Model basic = makeNoteForType(NoteType.BASIC);
// Enable sticky "Front" field
basic.getJSONArray("flds").getJSONObject(0).put("sticky", true);
String initFirstField = "Hello";
String initSecondField = "unused";
// /r/n on Windows under Robolectric
String newFirstField = "Hello" + FieldEditText.NEW_LINE + "World";
NoteEditor editor = getNoteEditorAdding(NoteType.BASIC).withFirstField(initFirstField).withSecondField(initSecondField).build();
assertThat(Arrays.asList(editor.getCurrentFieldStrings()), contains(initFirstField, initSecondField));
editor.setFieldValueFromUi(0, newFirstField);
assertThat(Arrays.asList(editor.getCurrentFieldStrings()), contains(newFirstField, initSecondField));
saveNote(editor);
RobolectricTest.waitForAsyncTasksToComplete();
List<String> actual = Arrays.asList(editor.getCurrentFieldStrings());
assertThat("newlines should be preserved, second field should be blanked", actual, contains(newFirstField, ""));
}
use of com.ichi2.anki.R in project Anki-Android by ankidroid.
the class Storage method _upgradeClozeModel.
private static void _upgradeClozeModel(Collection col, Model m) throws ConfirmModSchemaException {
m.put("type", Consts.MODEL_CLOZE);
// convert first template
JSONObject t = m.getJSONArray("tmpls").getJSONObject(0);
for (String type : new String[] { "qfmt", "afmt" }) {
// noinspection RegExpRedundantEscape // In Android, } should be escaped
t.put(type, t.getString(type).replaceAll("\\{\\{cloze:1:(.+?)\\}\\}", "{{cloze:$1}}"));
}
t.put("name", "Cloze");
// delete non-cloze cards for the model
JSONArray tmpls = m.getJSONArray("tmpls");
ArrayList<JSONObject> rem = new ArrayList<>();
for (JSONObject ta : tmpls.jsonObjectIterable()) {
if (!ta.getString("afmt").contains("{{cloze:")) {
rem.add(ta);
}
}
for (JSONObject r : rem) {
col.getModels().remTemplate(m, r);
}
JSONArray newTmpls = new JSONArray();
newTmpls.put(tmpls.getJSONObject(0));
m.put("tmpls", newTmpls);
Models._updateTemplOrds(m);
col.getModels().save(m);
}
use of com.ichi2.anki.R in project Anki-Android by ankidroid.
the class HttpSyncer method req.
/**
* Note: Return value must be closed
*/
@SuppressWarnings("CharsetObjectCanBeUsed")
public Response req(String method, InputStream fobj, int comp) throws UnknownHttpResponseException {
File tmpFileBuffer = null;
try {
String bdry = "--" + BOUNDARY;
StringWriter buf = new StringWriter();
// post vars
mPostVars.put("c", comp != 0 ? 1 : 0);
for (Map.Entry<String, Object> entry : mPostVars.entrySet()) {
buf.write(bdry + "\r\n");
buf.write(String.format(Locale.US, "Content-Disposition: form-data; name=\"%s\"\r\n\r\n%s\r\n", entry.getKey(), entry.getValue()));
}
tmpFileBuffer = File.createTempFile("syncer", ".tmp", new File(AnkiDroidApp.getCacheStorageDirectory()));
FileOutputStream fos = new FileOutputStream(tmpFileBuffer);
BufferedOutputStream bos = new BufferedOutputStream(fos);
GZIPOutputStream tgt;
// payload as raw data or json
if (fobj != null) {
// header
buf.write(bdry + "\r\n");
buf.write("Content-Disposition: form-data; name=\"data\"; filename=\"data\"\r\nContent-Type: application/octet-stream\r\n\r\n");
buf.close();
bos.write(buf.toString().getBytes("UTF-8"));
// write file into buffer, optionally compressing
int len;
BufferedInputStream bfobj = new BufferedInputStream(fobj);
byte[] chunk = new byte[65536];
if (comp != 0) {
tgt = new GZIPOutputStream(bos);
while ((len = bfobj.read(chunk)) >= 0) {
tgt.write(chunk, 0, len);
}
tgt.close();
bos = new BufferedOutputStream(new FileOutputStream(tmpFileBuffer, true));
} else {
while ((len = bfobj.read(chunk)) >= 0) {
bos.write(chunk, 0, len);
}
}
bos.write(("\r\n" + bdry + "--\r\n").getBytes("UTF-8"));
} else {
buf.close();
bos.write(buf.toString().getBytes("UTF-8"));
bos.write((bdry + "--\r\n").getBytes("UTF-8"));
}
bos.flush();
bos.close();
// connection headers
String url = Uri.parse(syncURL()).buildUpon().appendPath(method).toString();
Request.Builder requestBuilder = new Request.Builder();
requestBuilder.url(parseUrl(url));
// Set our request up to count upstream traffic including headers
requestBuilder.post(new CountingFileRequestBody(tmpFileBuffer, ANKI_POST_TYPE.toString(), num -> {
bytesSent.addAndGet(num);
publishProgress();
}));
Request httpPost = requestBuilder.build();
bytesSent.addAndGet(httpPost.headers().byteCount());
publishProgress();
try {
OkHttpClient httpClient = getHttpClient();
Response httpResponse = httpClient.newCall(httpPost).execute();
// we assume badAuthRaises flag from Anki Desktop always False
// so just throw new RuntimeException if response code not 200 or 403
Timber.d("TLSVersion in use is: %s", (httpResponse.handshake() != null ? httpResponse.handshake().tlsVersion() : "unknown"));
// Count downstream traffic including headers
bytesReceived.addAndGet(httpResponse.headers().byteCount());
try {
bytesReceived.addAndGet(httpResponse.body().contentLength());
} catch (NullPointerException npe) {
Timber.d(npe, "Unexpected null response body");
}
publishProgress();
assertOk(httpResponse);
return httpResponse;
} catch (SSLException e) {
Timber.e(e, "SSLException while building HttpClient");
throw new RuntimeException("SSLException while building HttpClient", e);
}
} catch (UnsupportedEncodingException e) {
throw new RuntimeException(e);
} catch (IOException e) {
Timber.e(e, "BasicHttpSyncer.sync: IOException");
throw new RuntimeException(e);
} finally {
if (tmpFileBuffer != null && tmpFileBuffer.exists()) {
tmpFileBuffer.delete();
}
}
}
use of com.ichi2.anki.R in project Anki-Android by ankidroid.
the class Syncer method chunk.
public JSONObject chunk() {
JSONObject buf = new JSONObject();
buf.put("done", false);
int lim = 250;
List<Integer> colTypes = null;
while (!mTablesLeft.isEmpty() && lim > 0) {
String curTable = mTablesLeft.getFirst();
if (mCursor == null) {
mCursor = cursorForTable(curTable);
}
colTypes = columnTypesForQuery(curTable);
JSONArray rows = new JSONArray();
int count = mCursor.getColumnCount();
int fetched = 0;
while (mCursor.moveToNext()) {
JSONArray r = new JSONArray();
for (int i = 0; i < count; i++) {
switch(colTypes.get(i)) {
case TYPE_STRING:
r.put(mCursor.getString(i));
break;
case TYPE_FLOAT:
r.put(mCursor.getDouble(i));
break;
case TYPE_INTEGER:
r.put(mCursor.getLong(i));
break;
}
}
rows.put(r);
if (++fetched == lim) {
break;
}
}
if (fetched != lim) {
// table is empty
mTablesLeft.removeFirst();
mCursor.close();
mCursor = null;
// if we're the client, mark the objects as having been sent
if (!mCol.getServer()) {
mCol.getDb().execute("UPDATE " + curTable + " SET usn=? WHERE usn=-1", mMaxUsn);
}
}
buf.put(curTable, rows);
lim -= fetched;
}
if (mTablesLeft.isEmpty()) {
buf.put("done", true);
}
return buf;
}
use of com.ichi2.anki.R in project Anki-Android by ankidroid.
the class ModelTest method test_req.
@Test
public void test_req() {
Collection col = getCol();
ModelManager mm = col.getModels();
Model basic = mm.byName("Basic");
assertTrue(basic.has("req"));
reqSize(basic);
JSONArray r = basic.getJSONArray("req").getJSONArray(0);
assertEquals(0, r.getInt(0));
assertTrue(Arrays.asList(new String[] { REQ_ANY, REQ_ALL }).contains(r.getString(1)));
assertEquals(1, r.getJSONArray(2).length());
assertEquals(0, r.getJSONArray(2).getInt(0));
Model opt = mm.byName("Basic (optional reversed card)");
reqSize(opt);
r = opt.getJSONArray("req").getJSONArray(0);
assertTrue(Arrays.asList(new String[] { REQ_ANY, REQ_ALL }).contains(r.getString(1)));
assertEquals(1, r.getJSONArray(2).length());
assertEquals(0, r.getJSONArray(2).getInt(0));
assertEquals(new JSONArray("[1,\"all\",[1,2]]"), opt.getJSONArray("req").getJSONArray(1));
// testing any
opt.getJSONArray("tmpls").getJSONObject(1).put("qfmt", "{{Back}}{{Add Reverse}}");
mm.save(opt, true);
assertEquals(new JSONArray("[1, \"any\", [1, 2]]"), opt.getJSONArray("req").getJSONArray(1));
// testing null
opt.getJSONArray("tmpls").getJSONObject(1).put("qfmt", "{{^Add Reverse}}{{/Add Reverse}}");
mm.save(opt, true);
assertEquals(new JSONArray("[1, \"none\", []]"), opt.getJSONArray("req").getJSONArray(1));
opt = mm.byName("Basic (type in the answer)");
reqSize(opt);
r = opt.getJSONArray("req").getJSONArray(0);
assertTrue(Arrays.asList(new String[] { REQ_ANY, REQ_ALL }).contains(r.getString(1)));
if (col.getModels() instanceof ModelsV16) {
assertEquals(new JSONArray("[0, 1]"), r.getJSONArray(2));
} else {
// TODO: Port anki@4e33775ed4346ef136ece6ef5efec5ba46057c6b
assertEquals(new JSONArray("[0]"), r.getJSONArray(2));
}
}
Aggregations