mirror of
git://xwords.git.sourceforge.net/gitroot/xwords/xwords
synced 2025-01-08 05:24:39 +01:00
Merge branch 'android_branch' into android_translate
This commit is contained in:
commit
e6fa514982
39 changed files with 927 additions and 373 deletions
|
@ -22,7 +22,7 @@
|
|||
to come from a domain that you own or have control over. -->
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="org.eehouse.android.xw4dbg"
|
||||
android:versionCode="95"
|
||||
android:versionCode="96"
|
||||
android:versionName="@string/app_version"
|
||||
>
|
||||
|
||||
|
@ -98,18 +98,15 @@
|
|||
|
||||
<activity android:name="BTInviteActivity"
|
||||
android:label="@string/bt_invite_title"
|
||||
android:theme="@android:style/Theme.Dialog"
|
||||
android:configChanges="keyboardHidden|orientation|screenSize"
|
||||
/>
|
||||
<activity android:name="SMSInviteActivity"
|
||||
android:label="@string/sms_invite_title"
|
||||
android:theme="@android:style/Theme.Dialog"
|
||||
android:configChanges="keyboardHidden|orientation|screenSize"
|
||||
android:screenOrientation="sensor"
|
||||
/>
|
||||
<activity android:name="RelayInviteActivity"
|
||||
android:label="@string/relay_invite_title"
|
||||
android:theme="@android:style/Theme.Dialog"
|
||||
android:configChanges="keyboardHidden|orientation|screenSize"
|
||||
/>
|
||||
|
||||
|
|
|
@ -63,9 +63,7 @@
|
|||
</extensions>
|
||||
</Objective-C-extensions>
|
||||
<XML>
|
||||
<option name="XML_KEEP_LINE_BREAKS" value="false" />
|
||||
<option name="XML_ALIGN_ATTRIBUTES" value="false" />
|
||||
<option name="XML_SPACE_INSIDE_EMPTY_TAG" value="true" />
|
||||
<option name="XML_LEGACY_SETTINGS_IMPORTED" value="true" />
|
||||
</XML>
|
||||
<codeStyleSettings language="XML">
|
||||
<option name="FORCE_REARRANGE_MODE" value="1" />
|
||||
|
@ -79,7 +77,7 @@
|
|||
<match>
|
||||
<AND>
|
||||
<NAME>xmlns:android</NAME>
|
||||
<XML_NAMESPACE />
|
||||
<XML_NAMESPACE>Namespace:</XML_NAMESPACE>
|
||||
</AND>
|
||||
</match>
|
||||
</rule>
|
||||
|
@ -89,7 +87,7 @@
|
|||
<match>
|
||||
<AND>
|
||||
<NAME>xmlns:.*</NAME>
|
||||
<XML_NAMESPACE />
|
||||
<XML_NAMESPACE>Namespace:</XML_NAMESPACE>
|
||||
</AND>
|
||||
</match>
|
||||
<order>BY_NAME</order>
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
to come from a domain that you own or have control over. -->
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="org.eehouse.android.xw4"
|
||||
android:versionCode="95"
|
||||
android:versionCode="96"
|
||||
android:versionName="@string/app_version"
|
||||
>
|
||||
|
||||
|
@ -94,18 +94,15 @@
|
|||
|
||||
<activity android:name="BTInviteActivity"
|
||||
android:label="@string/bt_invite_title"
|
||||
android:theme="@android:style/Theme.Dialog"
|
||||
android:configChanges="keyboardHidden|orientation|screenSize"
|
||||
/>
|
||||
<activity android:name="SMSInviteActivity"
|
||||
android:label="@string/sms_invite_title"
|
||||
android:theme="@android:style/Theme.Dialog"
|
||||
android:configChanges="keyboardHidden|orientation|screenSize"
|
||||
android:screenOrientation="sensor"
|
||||
/>
|
||||
<activity android:name="RelayInviteActivity"
|
||||
android:label="@string/relay_invite_title"
|
||||
android:theme="@android:style/Theme.Dialog"
|
||||
android:configChanges="keyboardHidden|orientation|screenSize"
|
||||
/>
|
||||
|
||||
|
|
|
@ -66,24 +66,17 @@
|
|||
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/rs" isTestSource="true" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/assets" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/classes" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/classes-proguard" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/debug" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/dependency-cache" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/dex" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/incremental" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/lint" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/manifests" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/mockable-android-14.jar" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/pre-dexed" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/proguard-rules" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/release" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/res" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/rs" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/symbols" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/tmp" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/outputs" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/reports" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/test-results" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/tmp" />
|
||||
</content>
|
||||
<orderEntry type="jdk" jdkName="Android API 14 Platform" jdkType="Android SDK" />
|
||||
|
|
|
@ -21,9 +21,9 @@ android {
|
|||
}
|
||||
|
||||
// Rename all output artifacts to include version information
|
||||
applicationVariants.all { variant ->
|
||||
renameArtifact(variant)
|
||||
}
|
||||
// applicationVariants.all { variant ->
|
||||
// renameArtifact(variant)
|
||||
// }
|
||||
|
||||
// flavorDimensions "variant", "abi"
|
||||
// productFlavors {
|
||||
|
@ -185,25 +185,25 @@ tasks.whenTaskAdded { theTask ->
|
|||
}
|
||||
}
|
||||
|
||||
def getVersionName() {
|
||||
try {
|
||||
def stdout = new ByteArrayOutputStream()
|
||||
exec {
|
||||
commandLine 'git', 'describe', '--dirty'
|
||||
standardOutput = stdout
|
||||
}
|
||||
return stdout.toString().trim()
|
||||
}
|
||||
catch (ignored) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
// def getVersionName() {
|
||||
// try {
|
||||
// def stdout = new ByteArrayOutputStream()
|
||||
// exec {
|
||||
// commandLine 'git', 'describe', '--dirty'
|
||||
// standardOutput = stdout
|
||||
// }
|
||||
// return stdout.toString().trim()
|
||||
// }
|
||||
// catch (ignored) {
|
||||
// return null;
|
||||
// }
|
||||
// }
|
||||
|
||||
def renameArtifact(variant) {
|
||||
variant.outputs.each { output ->
|
||||
def name = String.format( "XWords4-%s-%s.apk", variant.name,
|
||||
getVersionName() )
|
||||
output.outputFile = new File( (String)output.outputFile.parent,
|
||||
(String)name )
|
||||
}
|
||||
}
|
||||
// def renameArtifact(variant) {
|
||||
// variant.outputs.each { output ->
|
||||
// def name = String.format( "XWords4-%s-%s.apk", variant.name,
|
||||
// getVersionName() )
|
||||
// output.outputFile = new File( (String)output.outputFile.parent,
|
||||
// (String)name )
|
||||
// }
|
||||
// }
|
||||
|
|
|
@ -13,10 +13,15 @@
|
|||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<h2>Crosswords 4.4 beta 101 release</h2>
|
||||
<h2>Crosswords 4.4 beta 102 release</h2>
|
||||
|
||||
<p>This is the second of two releases that together fix stalling
|
||||
issues in network games.</p>
|
||||
<p>This release introduces "Rematch", a way to create new games from
|
||||
existing ones that short-circuits all the configuration and
|
||||
invitation nonsense. (Nonsense, anyway, after the first time.)
|
||||
Invitations are cleaned up. And it is the second of two releases
|
||||
that together fix stalling issues in network games. </p>
|
||||
|
||||
<p>I hope you like it!</p>
|
||||
|
||||
<div id="survey">
|
||||
<p>Please <a href="https://www.surveymonkey.com/s/GX3XLHR">take
|
||||
|
@ -26,8 +31,40 @@
|
|||
|
||||
<h3>New with this release</h3>
|
||||
<ul>
|
||||
<li>Fix to send correctly calculated identifier for game
|
||||
state.</li>
|
||||
<li>Rematch option allows creating a new game with the same
|
||||
opponents, and takes care of sending invitations to the
|
||||
remote device</li>
|
||||
|
||||
<li>Improve how invitations are created and sent, including
|
||||
making it easier to resend when necessary</li>
|
||||
|
||||
<li>Finish fixing problem with moves being dropped</li>
|
||||
|
||||
<li>Make it easier to "discover" and enable play-via-SMS (GSM
|
||||
phones only)</li>
|
||||
|
||||
<li>Fix memory leak that caused crashes if you opened a lot of
|
||||
games in a short period</li>
|
||||
|
||||
<li>Ask player for name the first time it's needed rather than
|
||||
when newly installed game first opened</li>
|
||||
|
||||
<li>Fix occasional failure to refresh thumbnails</li>
|
||||
|
||||
<li>Don't allow removing players when game is locked (in Game
|
||||
Config screen)</li>
|
||||
|
||||
<li>Put back long-tap (a.k.a. "context") menus in Games List
|
||||
screen. Because I like them</li>
|
||||
|
||||
<li>No reminders in robot games by default</li>
|
||||
|
||||
<li>Tweaks to Chat screen, and confirm before deleting chat
|
||||
history</li>
|
||||
|
||||
<li>Tweak notifications to make them more useful</li>
|
||||
|
||||
<li>Other minor bug fixes</li>
|
||||
</ul>
|
||||
|
||||
<p>(The full changelog
|
||||
|
@ -35,8 +72,6 @@
|
|||
|
||||
<h3>Next up</h3>
|
||||
<ul>
|
||||
<li>Offer "Rematch" when game's over (Easy via
|
||||
SMS and Bluetooth; harder via the internet/relay)</li>
|
||||
<li>Take advantage of Marshmallow's new permissions model (where
|
||||
the app only asks for them when it needs them.)
|
||||
</ul>
|
||||
|
|
|
@ -52,7 +52,6 @@
|
|||
android:text="@string/button_invite"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="10dip"
|
||||
/>
|
||||
|
||||
</LinearLayout>
|
||||
|
|
|
@ -95,5 +95,7 @@
|
|||
/>
|
||||
<item android:id="@+id/board_menu_game_netstats"
|
||||
android:title="@string/board_menu_game_netstats" />
|
||||
<item android:id="@+id/board_menu_game_invites"
|
||||
android:title="@string/board_menu_game_showInvites" />
|
||||
|
||||
</menu>
|
||||
|
|
|
@ -72,5 +72,7 @@
|
|||
|
||||
<item android:id="@+id/board_menu_game_netstats"
|
||||
android:title="@string/board_menu_game_netstats" />
|
||||
<item android:id="@+id/board_menu_game_invites"
|
||||
android:title="@string/board_menu_game_showInvites" />
|
||||
|
||||
</menu>
|
||||
|
|
|
@ -31,4 +31,9 @@
|
|||
<item android:id="@+id/games_game_deselect"
|
||||
android:title="@string/list_item_deselect"
|
||||
/>
|
||||
<!-- Debug only -->
|
||||
<item android:id="@+id/games_game_invites"
|
||||
android:title="@string/board_menu_game_showInvites"
|
||||
/>
|
||||
|
||||
</menu>
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
|
||||
<resources>
|
||||
<string name="app_version">4.4 beta 101</string>
|
||||
<string name="app_version">4.4 beta 102</string>
|
||||
</resources>
|
||||
|
|
|
@ -59,6 +59,8 @@
|
|||
<!-- Final state: game is over. -->
|
||||
<string name="summary_relay_gameover_fmt">Game over in room \"%1$s\"</string>
|
||||
|
||||
<string name="summary_invites_out">Players invited</string>
|
||||
|
||||
<!-- Games that have ended are listed with this string -->
|
||||
<string name="gameOver">Game over</string>
|
||||
<!-- Otherwise they're listed with this to give some indication of
|
||||
|
@ -545,6 +547,20 @@
|
|||
players. Would you like to invite someone to join -- assuming
|
||||
you haven\'t already?</item>
|
||||
</plurals>
|
||||
<plurals name="invite_sent_fmt">
|
||||
<item quantity="one">You have already invited a remote player to
|
||||
this game. We are waiting for him/her to respond. Please
|
||||
use the re-invite button if you think the invitation did not go
|
||||
out.</item>
|
||||
<item quantity="other">You have already sent %1$d unique
|
||||
invitations for this game. We are waiting for %2$d of the
|
||||
recipients to respond. Please use the re-invite button if you
|
||||
think the invitations did not go out.</item>
|
||||
</plurals>
|
||||
<string name="invited_msg">This game was created from an
|
||||
invitation you received. As soon as it is able to connect to the
|
||||
sender and any other invitees have arrived play will
|
||||
begin.</string>
|
||||
|
||||
<!-- Appended to message above if local device has NFC available -->
|
||||
<string name="invite_if_nfc">Or just Tap to Invite -- if the other
|
||||
|
@ -567,6 +583,15 @@
|
|||
this alert will not be dismissed until everybody has been invited
|
||||
and all invitations have been accepted.)</string>
|
||||
|
||||
<string name="invit_expl_sms_fmt">Invite sent via SMS to phone
|
||||
number %1$s on %2$s</string>
|
||||
<string name="invit_expl_bt_fmt">Invite sent via Bluetooth to
|
||||
paired device \"%1$s\" on %2$s</string>
|
||||
<string name="invit_expl_relay_fmt">Invite forwarded by the relay
|
||||
to another device on %1$s</string>
|
||||
<string name="invit_expl_notarget_fmt">Invite sent via %1$s on
|
||||
%2$s. Recipient unknown.</string>
|
||||
|
||||
<!-- Short for "points", this is shown at the right end of the
|
||||
tray in place of the first tile placed along with the points
|
||||
the current move would earn if committed. -->
|
||||
|
@ -1173,6 +1198,7 @@
|
|||
it immediately because an email or messaging app will be
|
||||
launched to send your invitation. -->
|
||||
<string name="newgame_invite">Invite now</string>
|
||||
<string name="newgame_invite_more">More info</string>
|
||||
<string name="newgame_drop_relay">Drop Relay</string>
|
||||
|
||||
<!-- section separator (white-on-gray bar) for third section:
|
||||
|
@ -1470,6 +1496,7 @@
|
|||
device, and the body that appears when you pull the notifications
|
||||
down. -->
|
||||
<string name="notify_title_fmt">Move in game %1$s</string>
|
||||
<string name="notify_title_turn_fmt">Your turn in game %1$s</string>
|
||||
<string name="notify_chat_title_fmt">Chat message in game %1$s</string>
|
||||
<string name="notify_chat_body_fmt">%1$s: %2$s</string>
|
||||
<!--
|
||||
|
@ -2016,6 +2043,9 @@
|
|||
<!-- -->
|
||||
<string name="connstat_net_fmt">Network status for game connected via
|
||||
%1$s:</string>
|
||||
<!-- First line of debug-only Invites list dialog -->
|
||||
<string name="invites_net_fmt">Invitations sent for game connected via
|
||||
%1$s:</string>
|
||||
<!-- -->
|
||||
<string name="connstat_succ">successful</string>
|
||||
<!-- -->
|
||||
|
@ -2439,12 +2469,16 @@
|
|||
|
||||
<string name="waiting_title">Waiting for players</string>
|
||||
<!-- Button for alert with title above -->
|
||||
<string name="waiting_invite_title">Waiting for response</string>
|
||||
<string name="waiting_rematch_title">Rematch in progress</string>
|
||||
<!-- Button for alert with title above -->
|
||||
<string name="button_wait">Wait</string>
|
||||
<string name="button_reinvite">Re-invite</string>
|
||||
|
||||
<string name="invite_stays">(This dialog will stay up until all
|
||||
remote players have connected. You can close the game if you
|
||||
expect it to take a while. They will still be able to
|
||||
connect.)</string>
|
||||
expect it to take a while. Remote players will still be able to
|
||||
connect, and you will be notified when they do.)</string>
|
||||
|
||||
<string name="nfc_just_tap">To invite via NFC just touch the back
|
||||
of this device against the one you want to invite—any time the
|
||||
|
@ -2461,10 +2495,10 @@
|
|||
<string name="button_edit">Edit</string>
|
||||
<string name="button_discard_changes">Discard changes</string>
|
||||
|
||||
<string name="rematch_msg">Issuing rematch invitation. You will
|
||||
see this message until it has been accepted.\n\nYou do not need to
|
||||
keep this game open while waiting. You will be notified when the
|
||||
game is ready to play.</string>
|
||||
<string name="rematch_sent_toast">Rematch invitations sent</string>
|
||||
<string name="rematch_msg">This game is hosting a rematch, and has
|
||||
sent an invitation. You will see this message until it has been
|
||||
accepted.</string>
|
||||
|
||||
<string name="not_again_enablepublic">Public rooms have been made
|
||||
an \"advanced\" feature in this release. If you were using them
|
||||
|
@ -2496,6 +2530,7 @@
|
|||
<string name="title_send_data_sms">Send SMS as data</string>
|
||||
<string name="summary_send_data_sms">(GSM phones only)</string>
|
||||
<string name="board_menu_game_netstats">Network stats</string>
|
||||
<string name="board_menu_game_showInvites">Show invites</string>
|
||||
<string name="netstats_title">Game network stats</string>
|
||||
|
||||
<string name="git_rev_title">Source version id</string>
|
||||
|
@ -2586,10 +2621,10 @@
|
|||
|
||||
<string name="str_no_hint_found">Cannot find any moves</string>
|
||||
|
||||
<string name="not_again_rematch_two_only">The Rematch button is
|
||||
disabled because, for now anyway, rematch is limited to two-person
|
||||
games. I think it\'s rare that people play with more than two. Let
|
||||
me know if I\'m wrong and I\'ll try harder to make it work.</string>
|
||||
<string name="not_again_rematch_two_only">Rematch is limited to
|
||||
two-person games, at least for now, because it\'s harder with more
|
||||
devices and I think it\'s rare that people play with more than
|
||||
two. Let me know if I\'m wrong and I\'ll up the priority.</string>
|
||||
|
||||
<string name="enable_relay_toself_title">Enable relay invites to self</string>
|
||||
<string name="enable_relay_toself_summary">(To aid testing and debugging)</string>
|
||||
|
|
|
@ -52,6 +52,7 @@
|
|||
<string name="summary_relay_conn_fmt">Emag ni yalp ni moor \"%1$s\"</string>
|
||||
<!-- Final state: game is over. -->
|
||||
<string name="summary_relay_gameover_fmt">Emag revo ni moor \"%1$s\"</string>
|
||||
<string name="summary_invites_out">Sreyalp detivni</string>
|
||||
<!-- Games that have ended are listed with this string -->
|
||||
<string name="gameOver">Emag revo</string>
|
||||
<!-- Otherwise they're listed with this to give some indication of
|
||||
|
@ -464,6 +465,20 @@
|
|||
sreyalp. Dluow uoy ekil ot etivni enoemos ot nioj -- gnimussa
|
||||
uoy nevah\'t ?ydaerla</item>
|
||||
</plurals>
|
||||
<plurals name="invite_sent_fmt">
|
||||
<item quantity="one">Uoy evah ydaerla detivni a etomer reyalp ot
|
||||
siht emag. Ew era gnitiaw rof reh/mih ot dnopser. Esaelp
|
||||
esu eht etivni-er nottub fi uoy kniht eht noitativni did ton og
|
||||
tuo.</item>
|
||||
<item quantity="other">Uoy evah ydaerla tnes %1$d euqinu
|
||||
snoitativni rof siht emag. Ew era gnitiaw rof %2$d fo eht
|
||||
stneipicer ot dnopser. Esaelp esu eht etivni-er nottub fi uoy
|
||||
kniht eht snoitativni did ton og tuo.</item>
|
||||
</plurals>
|
||||
<string name="invited_msg">Siht emag saw detaerc morf na
|
||||
noitativni uoy deviecer. Sa noos sa ti si elba ot tcennoc ot eht
|
||||
rednes dna yna rehto seetivni evah devirra yalp lliw
|
||||
nigeb.</string>
|
||||
<!-- Appended to message above if local device has NFC available -->
|
||||
<string name="invite_if_nfc">Ro tsuj Pat ot Etivni -- fi eht rehto
|
||||
ecived osla sah Diordna Gnimaeb dna si ybraen.</string>
|
||||
|
@ -482,6 +497,14 @@
|
|||
etomer sreyalp. Uoy nod\'t evah ot etivni meht lla ta ,ecno tub
|
||||
siht trela lliw ton eb dessimsid litnu ydobyreve sah neeb detivni
|
||||
dna lla snoitativni evah neeb detpecca.)</string>
|
||||
<string name="invit_expl_sms_fmt">Etivni tnes aiv SMS ot enohp
|
||||
rebmun %1$s no %2$s</string>
|
||||
<string name="invit_expl_bt_fmt">Etivni tnes aiv Htooteulb ot
|
||||
deriap ecived \"%1$s\" no %2$s</string>
|
||||
<string name="invit_expl_relay_fmt">Etivni dedrawrof yb eht yaler
|
||||
ot rehtona ecived no %1$s</string>
|
||||
<string name="invit_expl_notarget_fmt">Etivni tnes aiv %1$s no
|
||||
%2$s. Tneipicer nwonknu.</string>
|
||||
<!-- Short for "points", this is shown at the right end of the
|
||||
tray in place of the first tile placed along with the points
|
||||
the current move would earn if committed. -->
|
||||
|
@ -1009,6 +1032,7 @@
|
|||
it immediately because an email or messaging app will be
|
||||
launched to send your invitation. -->
|
||||
<string name="newgame_invite">Etivni won</string>
|
||||
<string name="newgame_invite_more">Erom ofni</string>
|
||||
<string name="newgame_drop_relay">Pord Yaler</string>
|
||||
<!-- section separator (white-on-gray bar) for third section:
|
||||
bluetooth games -->
|
||||
|
@ -1259,6 +1283,7 @@
|
|||
device, and the body that appears when you pull the notifications
|
||||
down. -->
|
||||
<string name="notify_title_fmt">Evom ni emag %1$s</string>
|
||||
<string name="notify_title_turn_fmt">Ruoy nrut ni emag %1$s</string>
|
||||
<string name="notify_chat_title_fmt">Tahc egassem ni emag %1$s</string>
|
||||
<string name="notify_chat_body_fmt">%1$s: %2$s</string>
|
||||
<!--
|
||||
|
@ -1741,6 +1766,9 @@
|
|||
<!-- -->
|
||||
<string name="connstat_net_fmt">Krowten sutats rof emag detcennoc aiv
|
||||
%1$s:</string>
|
||||
<!-- First line of debug-only Invites list dialog -->
|
||||
<string name="invites_net_fmt">Snoitativni tnes rof emag detcennoc aiv
|
||||
%1$s:</string>
|
||||
<!-- -->
|
||||
<string name="connstat_succ">lufsseccus</string>
|
||||
<!-- -->
|
||||
|
@ -2091,11 +2119,15 @@
|
|||
</string>
|
||||
<string name="waiting_title">Gnitiaw rof sreyalp</string>
|
||||
<!-- Button for alert with title above -->
|
||||
<string name="waiting_invite_title">Gnitiaw rof esnopser</string>
|
||||
<string name="waiting_rematch_title">Hctamer ni ssergorp</string>
|
||||
<!-- Button for alert with title above -->
|
||||
<string name="button_wait">Tiaw</string>
|
||||
<string name="button_reinvite">Etivni-er</string>
|
||||
<string name="invite_stays">sIht( golaid lliw yats pu litnu lla
|
||||
etomer sreyalp evah detcennoc. Uoy nac esolc eht emag fi uoy
|
||||
tcepxe ti ot ekat a elihw. Yeht lliw llits eb elba ot
|
||||
tcennoc.)</string>
|
||||
tcepxe ti ot ekat a elihw. Etomer sreyalp lliw llits eb elba ot
|
||||
,tcennoc dna uoy lliw eb deifiton nehw yeht od.)</string>
|
||||
<string name="nfc_just_tap">Ot etivni aiv CFN tsuj hcuot eht kcab
|
||||
fo siht ecived tsniaga eht eno uoy tnaw ot yna—etivni emit eht
|
||||
emag si nepo.</string>
|
||||
|
@ -2108,10 +2140,10 @@
|
|||
tide ot evig ti a yaw ot ?tcennoc</string>
|
||||
<string name="button_edit">Tide</string>
|
||||
<string name="button_discard_changes">Dracsid segnahc</string>
|
||||
<string name="rematch_msg">Gniussi hctamer noitativni. Uoy lliw
|
||||
ees siht egassem litnu ti sah neeb detpecca.\n\nUoy od ton deen ot
|
||||
peek siht emag nepo elihw gnitiaw. Uoy lliw eb deifiton nehw eht
|
||||
emag si ydaer ot yalp.</string>
|
||||
<string name="rematch_sent_toast">Hctamer snoitativni tnes</string>
|
||||
<string name="rematch_msg">Siht emag si gnitsoh a ,hctamer dna sah
|
||||
tnes na noitativni. Uoy lliw ees siht egassem litnu ti sah neeb
|
||||
detpecca.</string>
|
||||
<string name="not_again_enablepublic">Cilbup smoor evah neeb edam
|
||||
na \"decnavda\" erutaef ni siht esaeler. Fi uoy erew gnisu meht
|
||||
dna tnaw meht ,kcab elbane meht won. Uoy nac nrut meht ffo niaga
|
||||
|
@ -2139,6 +2171,7 @@
|
|||
<string name="title_send_data_sms">Dnes SMS sa atad</string>
|
||||
<string name="summary_send_data_sms">mSG( senohp )ylno</string>
|
||||
<string name="board_menu_game_netstats">Krowten stats</string>
|
||||
<string name="board_menu_game_showInvites">Wohs setivni</string>
|
||||
<string name="netstats_title">Emag krowten stats</string>
|
||||
<string name="git_rev_title">Ecruos noisrev di</string>
|
||||
<string name="devid_title">Ecived DI no( )yaler</string>
|
||||
|
@ -2210,10 +2243,10 @@
|
|||
<string name="not_again_comms_bt">Esu Htooteulb ot yalp tsniaga a
|
||||
ybraen ecived taht\'s \"deriap\" htiw sruoy.</string>
|
||||
<string name="str_no_hint_found">Tonnac dnif yna sevom</string>
|
||||
<string name="not_again_rematch_two_only">Eht Hctamer nottub si
|
||||
delbasid ,esuaceb rof won ,yawyna hctamer si detimil ot nosrep-owt
|
||||
semag. I kniht ti\'s erar taht elpoep yalp htiw erom naht owt. Tel
|
||||
em wonk fi I\'m gnorw dna I\'ll yrt redrah ot ekam ti krow.</string>
|
||||
<string name="not_again_rematch_two_only">Hctamer si detimil ot
|
||||
nosrep-owt ,semag ta tsael rof ,won esuaceb ti\'s redrah htiw erom
|
||||
secived dna I kniht ti\'s erar taht elpoep yalp htiw erom naht
|
||||
owt. Tel em wonk fi I\'m gnorw dna I\'ll pu eht ytiroirp.</string>
|
||||
<string name="enable_relay_toself_title">Elbane yaler setivni ot fles</string>
|
||||
<string name="enable_relay_toself_summary">oT( dia gnitset dna )gniggubed</string>
|
||||
<!-- Shown after "resend messages" menuitem chosen -->
|
||||
|
|
|
@ -52,6 +52,7 @@
|
|||
<string name="summary_relay_conn_fmt">GAME IN PLAY IN ROOM \"%1$s\"</string>
|
||||
<!-- Final state: game is over. -->
|
||||
<string name="summary_relay_gameover_fmt">GAME OVER IN ROOM \"%1$s\"</string>
|
||||
<string name="summary_invites_out">PLAYERS INVITED</string>
|
||||
<!-- Games that have ended are listed with this string -->
|
||||
<string name="gameOver">GAME OVER</string>
|
||||
<!-- Otherwise they're listed with this to give some indication of
|
||||
|
@ -464,6 +465,20 @@
|
|||
PLAYERS. WOULD YOU LIKE TO INVITE SOMEONE TO JOIN -- ASSUMING
|
||||
YOU HAVEN\'T ALREADY?</item>
|
||||
</plurals>
|
||||
<plurals name="invite_sent_fmt">
|
||||
<item quantity="one">YOU HAVE ALREADY INVITED A REMOTE PLAYER TO
|
||||
THIS GAME. WE ARE WAITING FOR HIM/HER TO RESPOND. PLEASE
|
||||
USE THE RE-INVITE BUTTON IF YOU THINK THE INVITATION DID NOT GO
|
||||
OUT.</item>
|
||||
<item quantity="other">YOU HAVE ALREADY SENT %1$d UNIQUE
|
||||
INVITATIONS FOR THIS GAME. WE ARE WAITING FOR %2$d OF THE
|
||||
RECIPIENTS TO RESPOND. PLEASE USE THE RE-INVITE BUTTON IF YOU
|
||||
THINK THE INVITATIONS DID NOT GO OUT.</item>
|
||||
</plurals>
|
||||
<string name="invited_msg">THIS GAME WAS CREATED FROM AN
|
||||
INVITATION YOU RECEIVED. AS SOON AS IT IS ABLE TO CONNECT TO THE
|
||||
SENDER AND ANY OTHER INVITEES HAVE ARRIVED PLAY WILL
|
||||
BEGIN.</string>
|
||||
<!-- Appended to message above if local device has NFC available -->
|
||||
<string name="invite_if_nfc">OR JUST TAP TO INVITE -- IF THE OTHER
|
||||
DEVICE ALSO HAS ANDROID BEAMING AND IS NEARBY.</string>
|
||||
|
@ -482,6 +497,14 @@
|
|||
REMOTE PLAYERS. YOU DON\'T HAVE TO INVITE THEM ALL AT ONCE, BUT
|
||||
THIS ALERT WILL NOT BE DISMISSED UNTIL EVERYBODY HAS BEEN INVITED
|
||||
AND ALL INVITATIONS HAVE BEEN ACCEPTED.)</string>
|
||||
<string name="invit_expl_sms_fmt">INVITE SENT VIA SMS TO PHONE
|
||||
NUMBER %1$s ON %2$s</string>
|
||||
<string name="invit_expl_bt_fmt">INVITE SENT VIA BLUETOOTH TO
|
||||
PAIRED DEVICE \"%1$s\" ON %2$s</string>
|
||||
<string name="invit_expl_relay_fmt">INVITE FORWARDED BY THE RELAY
|
||||
TO ANOTHER DEVICE ON %1$s</string>
|
||||
<string name="invit_expl_notarget_fmt">INVITE SENT VIA %1$s ON
|
||||
%2$s. RECIPIENT UNKNOWN.</string>
|
||||
<!-- Short for "points", this is shown at the right end of the
|
||||
tray in place of the first tile placed along with the points
|
||||
the current move would earn if committed. -->
|
||||
|
@ -1009,6 +1032,7 @@
|
|||
it immediately because an email or messaging app will be
|
||||
launched to send your invitation. -->
|
||||
<string name="newgame_invite">INVITE NOW</string>
|
||||
<string name="newgame_invite_more">MORE INFO</string>
|
||||
<string name="newgame_drop_relay">DROP RELAY</string>
|
||||
<!-- section separator (white-on-gray bar) for third section:
|
||||
bluetooth games -->
|
||||
|
@ -1259,6 +1283,7 @@
|
|||
device, and the body that appears when you pull the notifications
|
||||
down. -->
|
||||
<string name="notify_title_fmt">MOVE IN GAME %1$s</string>
|
||||
<string name="notify_title_turn_fmt">YOUR TURN IN GAME %1$s</string>
|
||||
<string name="notify_chat_title_fmt">CHAT MESSAGE IN GAME %1$s</string>
|
||||
<string name="notify_chat_body_fmt">%1$s: %2$s</string>
|
||||
<!--
|
||||
|
@ -1741,6 +1766,9 @@
|
|||
<!-- -->
|
||||
<string name="connstat_net_fmt">NETWORK STATUS FOR GAME CONNECTED VIA
|
||||
%1$s:</string>
|
||||
<!-- First line of debug-only Invites list dialog -->
|
||||
<string name="invites_net_fmt">INVITATIONS SENT FOR GAME CONNECTED VIA
|
||||
%1$s:</string>
|
||||
<!-- -->
|
||||
<string name="connstat_succ">SUCCESSFUL</string>
|
||||
<!-- -->
|
||||
|
@ -2091,11 +2119,15 @@
|
|||
</string>
|
||||
<string name="waiting_title">WAITING FOR PLAYERS</string>
|
||||
<!-- Button for alert with title above -->
|
||||
<string name="waiting_invite_title">WAITING FOR RESPONSE</string>
|
||||
<string name="waiting_rematch_title">REMATCH IN PROGRESS</string>
|
||||
<!-- Button for alert with title above -->
|
||||
<string name="button_wait">WAIT</string>
|
||||
<string name="button_reinvite">RE-INVITE</string>
|
||||
<string name="invite_stays">(THIS DIALOG WILL STAY UP UNTIL ALL
|
||||
REMOTE PLAYERS HAVE CONNECTED. YOU CAN CLOSE THE GAME IF YOU
|
||||
EXPECT IT TO TAKE A WHILE. THEY WILL STILL BE ABLE TO
|
||||
CONNECT.)</string>
|
||||
EXPECT IT TO TAKE A WHILE. REMOTE PLAYERS WILL STILL BE ABLE TO
|
||||
CONNECT, AND YOU WILL BE NOTIFIED WHEN THEY DO.)</string>
|
||||
<string name="nfc_just_tap">TO INVITE VIA NFC JUST TOUCH THE BACK
|
||||
OF THIS DEVICE AGAINST THE ONE YOU WANT TO INVITE—ANY TIME THE
|
||||
GAME IS OPEN.</string>
|
||||
|
@ -2108,10 +2140,10 @@
|
|||
EDIT TO GIVE IT A WAY TO CONNECT?</string>
|
||||
<string name="button_edit">EDIT</string>
|
||||
<string name="button_discard_changes">DISCARD CHANGES</string>
|
||||
<string name="rematch_msg">ISSUING REMATCH INVITATION. YOU WILL
|
||||
SEE THIS MESSAGE UNTIL IT HAS BEEN ACCEPTED.\n\nYOU DO NOT NEED TO
|
||||
KEEP THIS GAME OPEN WHILE WAITING. YOU WILL BE NOTIFIED WHEN THE
|
||||
GAME IS READY TO PLAY.</string>
|
||||
<string name="rematch_sent_toast">REMATCH INVITATIONS SENT</string>
|
||||
<string name="rematch_msg">THIS GAME IS HOSTING A REMATCH, AND HAS
|
||||
SENT AN INVITATION. YOU WILL SEE THIS MESSAGE UNTIL IT HAS BEEN
|
||||
ACCEPTED.</string>
|
||||
<string name="not_again_enablepublic">PUBLIC ROOMS HAVE BEEN MADE
|
||||
AN \"ADVANCED\" FEATURE IN THIS RELEASE. IF YOU WERE USING THEM
|
||||
AND WANT THEM BACK, ENABLE THEM NOW. YOU CAN TURN THEM OFF AGAIN
|
||||
|
@ -2139,6 +2171,7 @@
|
|||
<string name="title_send_data_sms">SEND SMS AS DATA</string>
|
||||
<string name="summary_send_data_sms">(GSM PHONES ONLY)</string>
|
||||
<string name="board_menu_game_netstats">NETWORK STATS</string>
|
||||
<string name="board_menu_game_showInvites">SHOW INVITES</string>
|
||||
<string name="netstats_title">GAME NETWORK STATS</string>
|
||||
<string name="git_rev_title">SOURCE VERSION ID</string>
|
||||
<string name="devid_title">DEVICE ID (ON RELAY)</string>
|
||||
|
@ -2210,10 +2243,10 @@
|
|||
<string name="not_again_comms_bt">USE BLUETOOTH TO PLAY AGAINST A
|
||||
NEARBY DEVICE THAT\'S \"PAIRED\" WITH YOURS.</string>
|
||||
<string name="str_no_hint_found">CANNOT FIND ANY MOVES</string>
|
||||
<string name="not_again_rematch_two_only">THE REMATCH BUTTON IS
|
||||
DISABLED BECAUSE, FOR NOW ANYWAY, REMATCH IS LIMITED TO TWO-PERSON
|
||||
GAMES. I THINK IT\'S RARE THAT PEOPLE PLAY WITH MORE THAN TWO. LET
|
||||
ME KNOW IF I\'M WRONG AND I\'LL TRY HARDER TO MAKE IT WORK.</string>
|
||||
<string name="not_again_rematch_two_only">REMATCH IS LIMITED TO
|
||||
TWO-PERSON GAMES, AT LEAST FOR NOW, BECAUSE IT\'S HARDER WITH MORE
|
||||
DEVICES AND I THINK IT\'S RARE THAT PEOPLE PLAY WITH MORE THAN
|
||||
TWO. LET ME KNOW IF I\'M WRONG AND I\'LL UP THE PRIORITY.</string>
|
||||
<string name="enable_relay_toself_title">ENABLE RELAY INVITES TO SELF</string>
|
||||
<string name="enable_relay_toself_summary">(TO AID TESTING AND DEBUGGING)</string>
|
||||
<!-- Shown after "resend messages" menuitem chosen -->
|
||||
|
|
|
@ -3503,4 +3503,4 @@ pour la langue</string>
|
|||
|
||||
<string name="not_again_dfltname_fmt">Vous utilisez le nom par défaut de joueur \"%1$s\". Souhaitez-vous le personnaliser avec votre propre nom avant de créer cette partie ?</string>
|
||||
|
||||
</resources>
|
||||
</resources>
|
||||
|
|
|
@ -44,21 +44,28 @@ import java.util.Iterator;
|
|||
import junit.framework.Assert;
|
||||
|
||||
import org.eehouse.android.xw4.DlgDelegate.Action;
|
||||
import org.eehouse.android.xw4.DBUtils.SentInvitesInfo;
|
||||
import org.eehouse.android.xw4.DlgDelegate.DlgClickNotify.InviteMeans;
|
||||
|
||||
public class BTInviteDelegate extends InviteDelegate {
|
||||
|
||||
private Activity m_activity;
|
||||
private Set<String> m_checked;
|
||||
private Set<LinearLayout> m_checked;
|
||||
private Map<String, Integer> m_counts;
|
||||
private boolean m_setChecked;
|
||||
private BTDevsAdapter m_adapter;
|
||||
|
||||
public static void launchForResult( Activity activity, int nMissing,
|
||||
public static void launchForResult( Activity activity, int nMissing,
|
||||
SentInvitesInfo info,
|
||||
RequestCode requestCode )
|
||||
{
|
||||
Assert.assertTrue( 0 < nMissing ); // don't call if nMissing == 0
|
||||
Intent intent = new Intent( activity, BTInviteActivity.class );
|
||||
intent.putExtra( INTENT_KEY_NMISSING, nMissing );
|
||||
if ( null != info ) {
|
||||
String lastDev = info.getLastDev( InviteMeans.BLUETOOTH );
|
||||
intent.putExtra( INTENT_KEY_LASTDEV, lastDev );
|
||||
}
|
||||
activity.startActivityForResult( intent, requestCode.ordinal() );
|
||||
}
|
||||
|
||||
|
@ -71,7 +78,7 @@ public class BTInviteDelegate extends InviteDelegate {
|
|||
@Override
|
||||
protected void init( Bundle savedInstanceState )
|
||||
{
|
||||
m_checked = new HashSet<String>();
|
||||
m_checked = new HashSet<LinearLayout>();
|
||||
m_counts = new HashMap<String, Integer>();
|
||||
|
||||
String msg = getString( R.string.bt_pick_addall_button );
|
||||
|
@ -149,9 +156,11 @@ public class BTInviteDelegate extends InviteDelegate {
|
|||
}
|
||||
|
||||
int nxt = 0;
|
||||
for ( Iterator<String> iter = m_checked.iterator();
|
||||
for ( Iterator<LinearLayout> iter = m_checked.iterator();
|
||||
iter.hasNext(); ) {
|
||||
String btAddr = iter.next();
|
||||
LinearLayout layout = iter.next();
|
||||
CheckBox box = (CheckBox)layout.findViewById( R.id.inviter_check );
|
||||
String btAddr = (String)box.getTag();
|
||||
devs[nxt] = btAddr;
|
||||
if ( null != counts ) {
|
||||
counts[nxt] = m_counts.get( btAddr );
|
||||
|
@ -178,6 +187,7 @@ public class BTInviteDelegate extends InviteDelegate {
|
|||
private class BTDevsAdapter extends XWListAdapter {
|
||||
private String[] m_devAddrs;
|
||||
private String[] m_devNames;
|
||||
|
||||
public BTDevsAdapter( String[] btAddrs, String[] btNames )
|
||||
{
|
||||
super( null == btAddrs? 0 : btAddrs.length );
|
||||
|
@ -189,7 +199,7 @@ public class BTInviteDelegate extends InviteDelegate {
|
|||
|
||||
public View getView( int position, View convertView, ViewGroup parent ) {
|
||||
final String btAddr = m_devAddrs[position];
|
||||
LinearLayout layout = (LinearLayout)inflate( R.layout.btinviter_item );
|
||||
final LinearLayout layout = (LinearLayout)inflate( R.layout.btinviter_item );
|
||||
CheckBox box = (CheckBox)layout.findViewById( R.id.inviter_check );
|
||||
box.setText( m_devNames[position] );
|
||||
box.setTag( btAddr );
|
||||
|
@ -223,12 +233,19 @@ public class BTInviteDelegate extends InviteDelegate {
|
|||
CompoundButton.OnCheckedChangeListener listener =
|
||||
new CompoundButton.OnCheckedChangeListener() {
|
||||
public void onCheckedChanged( CompoundButton buttonView,
|
||||
boolean isChecked )
|
||||
{
|
||||
boolean isChecked ) {
|
||||
if ( isChecked ) {
|
||||
m_checked.add( btAddr );
|
||||
if ( 1 == m_nMissing && 1 == m_checked.size() ) {
|
||||
LinearLayout checked = m_checked.iterator().next();
|
||||
CheckBox box = (CheckBox)checked
|
||||
.findViewById( R.id.inviter_check );
|
||||
box.setChecked( false );
|
||||
m_checked.clear();
|
||||
}
|
||||
|
||||
m_checked.add( layout );
|
||||
} else {
|
||||
m_checked.remove( btAddr );
|
||||
m_checked.remove( layout );
|
||||
// User's now making changes; don't check new views
|
||||
m_setChecked = false;
|
||||
}
|
||||
|
@ -237,7 +254,10 @@ public class BTInviteDelegate extends InviteDelegate {
|
|||
};
|
||||
box.setOnCheckedChangeListener( listener );
|
||||
|
||||
if ( m_setChecked || m_checked.contains( btAddr ) ) {
|
||||
if ( m_setChecked || m_checked.contains( layout ) ) {
|
||||
box.setChecked( true );
|
||||
} else if ( null != m_lastDev && m_lastDev.equals( btAddr ) ) {
|
||||
m_lastDev = null;
|
||||
box.setChecked( true );
|
||||
}
|
||||
return layout;
|
||||
|
|
|
@ -129,13 +129,7 @@ public class BTService extends XWService {
|
|||
NetLaunchInfo m_nli;
|
||||
|
||||
public BTQueueElem( BTCmd cmd ) { m_cmd = cmd; m_failCount = 0; }
|
||||
// public BTQueueElem( BTCmd cmd, String btAddr,
|
||||
// int gameID, String gameName, int lang,
|
||||
// String dict, int nPlayersT, int nPlayersH ) {
|
||||
// this( cmd, null, btAddr, gameID );
|
||||
// m_lang = lang; m_dict = dict; m_nPlayersT = nPlayersT;
|
||||
// m_nPlayersH = nPlayersH; m_gameName = gameName;
|
||||
// }
|
||||
|
||||
public BTQueueElem( BTCmd cmd, byte[] buf, String btAddr, int gameID ) {
|
||||
this( cmd );
|
||||
Assert.assertTrue( null != btAddr && 0 < btAddr.length() );
|
||||
|
@ -271,23 +265,6 @@ public class BTService extends XWService {
|
|||
context.startService( intent );
|
||||
}
|
||||
|
||||
// public static void inviteRemote( Context context, String btAddr,
|
||||
// int gameID, String initialName, int lang,
|
||||
// String dict, int nPlayersT, int nPlayersH )
|
||||
// {
|
||||
// Intent intent = getIntentTo( context, INVITE );
|
||||
// intent.putExtra( GAMEID_KEY, gameID );
|
||||
// intent.putExtra( ADDR_KEY, btAddr );
|
||||
// Assert.assertNotNull( initialName );
|
||||
// intent.putExtra( GAMENAME_KEY, initialName );
|
||||
// intent.putExtra( LANG_KEY, lang );
|
||||
// intent.putExtra( DICT_KEY, dict );
|
||||
// intent.putExtra( NTO_KEY, nPlayersT );
|
||||
// intent.putExtra( NHE_KEY, nPlayersH );
|
||||
|
||||
// context.startService( intent );
|
||||
// }
|
||||
|
||||
public static void inviteRemote( Context context, String btAddr,
|
||||
NetLaunchInfo nli )
|
||||
{
|
||||
|
@ -612,6 +589,7 @@ public class BTService extends XWService {
|
|||
CommsAddrRec addr = new CommsAddrRec( host.getName(),
|
||||
host.getAddress() );
|
||||
|
||||
boolean[] isLocalP = new boolean[1];
|
||||
for ( long rowid : rowids ) {
|
||||
boolean consumed =
|
||||
BoardDelegate.feedMessage( rowid, buffer, addr );
|
||||
|
@ -620,10 +598,12 @@ public class BTService extends XWService {
|
|||
new GameUtils.BackMoveResult();
|
||||
if ( GameUtils.feedMessage( BTService.this, rowid,
|
||||
buffer, addr,
|
||||
m_btMsgSink, bmr ) ) {
|
||||
m_btMsgSink, bmr,
|
||||
isLocalP ) ) {
|
||||
consumed = true;
|
||||
GameUtils.postMoveNotification( BTService.this,
|
||||
rowid, bmr );
|
||||
rowid, bmr,
|
||||
isLocalP[0] );
|
||||
}
|
||||
}
|
||||
if ( !consumed ) {
|
||||
|
@ -1144,7 +1124,8 @@ public class BTService extends XWService {
|
|||
if ( null == rowids || 0 == rowids.length ) {
|
||||
CommsAddrRec addr = nli.makeAddrRec( BTService.this );
|
||||
long rowid = GameUtils.makeNewMultiGame( BTService.this, nli,
|
||||
m_btMsgSink, null );
|
||||
m_btMsgSink,
|
||||
getUtilCtxt() );
|
||||
if ( DBUtils.ROWID_NOTFOUND == rowid ) {
|
||||
result = BTCmd.INVITE_FAILED;
|
||||
} else {
|
||||
|
@ -1249,13 +1230,17 @@ public class BTService extends XWService {
|
|||
@Override
|
||||
public int sendViaBluetooth( byte[] buf, int gameID, CommsAddrRec addr )
|
||||
{
|
||||
int nSent = -1;
|
||||
String btAddr = getSafeAddr( addr );
|
||||
|
||||
Assert.assertTrue( addr.contains( CommsConnType.COMMS_CONN_BT ) );
|
||||
m_sender.add( new BTQueueElem( BTCmd.MESG_SEND, buf,
|
||||
btAddr, gameID ) );
|
||||
return buf.length;
|
||||
if ( null != btAddr && 0 < btAddr.length() ) {
|
||||
m_sender.add( new BTQueueElem( BTCmd.MESG_SEND, buf, btAddr,
|
||||
gameID ) );
|
||||
nSent = buf.length;
|
||||
} else {
|
||||
DbgUtils.logf( "sendViaBluetooth(): no addr for dev %s",
|
||||
addr.bt_hostName );
|
||||
}
|
||||
return nSent;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/* -*- compile-command: "find-and-ant.sh debug install"; -*- */
|
||||
/*
|
||||
* Copyright 2009 - 2014 by Eric House (xwords@eehouse.org). All
|
||||
* Copyright 2009 - 2016 by Eric House (xwords@eehouse.org). All
|
||||
* rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
|
@ -53,6 +53,7 @@ import java.util.concurrent.Semaphore;
|
|||
|
||||
import junit.framework.Assert;
|
||||
|
||||
import org.eehouse.android.xw4.DBUtils.SentInvitesInfo;
|
||||
import org.eehouse.android.xw4.DlgDelegate.Action;
|
||||
import org.eehouse.android.xw4.DlgDelegate.DlgClickNotify.InviteMeans;
|
||||
import org.eehouse.android.xw4.jni.*;
|
||||
|
@ -86,7 +87,7 @@ public class BoardDelegate extends DelegateBase
|
|||
private GameLock m_gameLock;
|
||||
private CurGameInfo m_gi;
|
||||
private GameSummary m_summary;
|
||||
private boolean m_relayConnected;
|
||||
private boolean m_relayMissing;
|
||||
private CommsTransport m_xport;
|
||||
private Handler m_handler = null;
|
||||
private TimerRunnable[] m_timers;
|
||||
|
@ -96,6 +97,7 @@ public class BoardDelegate extends DelegateBase
|
|||
private View m_tradeButtons;
|
||||
private Button m_exchCommmitButton;
|
||||
private Button m_exchCancelButton;
|
||||
private SentInvitesInfo m_sentInfo;
|
||||
|
||||
private ArrayList<String> m_pendingChats;
|
||||
|
||||
|
@ -138,7 +140,6 @@ public class BoardDelegate extends DelegateBase
|
|||
private int m_nGuestDevs = -1;
|
||||
private boolean m_haveInvited = false;
|
||||
private boolean m_overNotShown;
|
||||
private boolean m_rematchInvitesSent = false;
|
||||
|
||||
private static Set<BoardDelegate> s_this = new HashSet<BoardDelegate>();
|
||||
|
||||
|
@ -430,24 +431,38 @@ public class BoardDelegate extends DelegateBase
|
|||
lstnr = new OnClickListener() {
|
||||
public void onClick( DialogInterface dialog,
|
||||
int item ) {
|
||||
if ( m_relayConnected ||
|
||||
if ( !m_relayMissing ||
|
||||
! m_connTypes.contains(CommsConnType.COMMS_CONN_RELAY) ) {
|
||||
showInviteChoicesThen( Action.LAUNCH_INVITE_ACTION );
|
||||
Assert.assertTrue( 0 < m_nMissing );
|
||||
if ( m_summary.hasRematchInfo() ) {
|
||||
tryRematchInvites( true );
|
||||
} else {
|
||||
showInviteChoicesThen( Action.LAUNCH_INVITE_ACTION,
|
||||
m_sentInfo );
|
||||
}
|
||||
} else {
|
||||
askDropRelay();
|
||||
}
|
||||
}
|
||||
};
|
||||
OnClickListener lstnr2 = new OnClickListener() {
|
||||
OnClickListener lstnrWait = new OnClickListener() {
|
||||
public void onClick( DialogInterface dialog,
|
||||
int item ) {
|
||||
finish();
|
||||
}
|
||||
};
|
||||
OnClickListener lstnrMore = new OnClickListener() {
|
||||
public void onClick( DialogInterface dialog,
|
||||
int item ) {
|
||||
showOKOnlyDialog( m_sentInfo.getAsText( m_activity ) );
|
||||
}
|
||||
};
|
||||
|
||||
dialog = ab.setTitle( "foo" )
|
||||
.setMessage( "" )
|
||||
.setPositiveButton( "", lstnr )
|
||||
.setNegativeButton( R.string.button_wait, lstnr2 )
|
||||
.setNegativeButton( R.string.button_wait, lstnrWait )
|
||||
.setNeutralButton( R.string.newgame_invite_more, lstnrMore )
|
||||
.setOnCancelListener( new OnCancelListener() {
|
||||
public void onCancel( DialogInterface dialog ) {
|
||||
finish();
|
||||
|
@ -476,37 +491,55 @@ public class BoardDelegate extends DelegateBase
|
|||
AlertDialog ad = (AlertDialog)dialog;
|
||||
String message;
|
||||
int titleID;
|
||||
boolean nukeButton = false;
|
||||
boolean nukeInviteButton = false;
|
||||
boolean nukeNeutButton = true;
|
||||
int buttonTxt = R.string.newgame_invite;
|
||||
if ( m_summary.hasRematchInfo() ) {
|
||||
titleID = R.string.info_title;;
|
||||
message = getString( R.string.rematch_msg );
|
||||
nukeButton = true;
|
||||
} else {
|
||||
if ( !m_relayConnected ) {
|
||||
titleID = R.string.seeking_relay;
|
||||
// If relay is only means, don't allow at all
|
||||
boolean relayOnly = 1 >= m_connTypes.size();
|
||||
nukeButton = relayOnly;
|
||||
message = getString( R.string.no_relay_conn );
|
||||
if ( NetStateCache.netAvail( m_activity )
|
||||
&& NetStateCache.onWifi() ) {
|
||||
message += getString( R.string.wifi_warning );
|
||||
}
|
||||
if ( !relayOnly ) {
|
||||
CommsConnTypeSet without = (CommsConnTypeSet)
|
||||
m_connTypes.clone();
|
||||
without.remove( CommsConnType.COMMS_CONN_RELAY );
|
||||
message += "\n\n"
|
||||
+ getString( R.string.drop_relay_warning_fmt,
|
||||
without.toString( m_activity ) );
|
||||
buttonTxt = R.string.newgame_drop_relay;
|
||||
if ( m_relayMissing ) {
|
||||
titleID = R.string.seeking_relay;
|
||||
// If relay is only means, don't allow at all
|
||||
boolean relayOnly = 1 >= m_connTypes.size();
|
||||
nukeInviteButton = relayOnly;
|
||||
message = getString( R.string.no_relay_conn );
|
||||
if ( NetStateCache.netAvail( m_activity )
|
||||
&& NetStateCache.onWifi() ) {
|
||||
message += getString( R.string.wifi_warning );
|
||||
}
|
||||
if ( !relayOnly ) {
|
||||
CommsConnTypeSet without = (CommsConnTypeSet)
|
||||
m_connTypes.clone();
|
||||
without.remove( CommsConnType.COMMS_CONN_RELAY );
|
||||
message += "\n\n"
|
||||
+ getString( R.string.drop_relay_warning_fmt,
|
||||
without.toString( m_activity ) );
|
||||
buttonTxt = R.string.newgame_drop_relay;
|
||||
}
|
||||
} else {
|
||||
m_sentInfo = DBUtils.getInvitesFor( m_activity, m_rowid );
|
||||
int nSent = m_sentInfo.getMinPlayerCount();
|
||||
boolean invitesSent = nSent >= m_nMissing;
|
||||
if ( invitesSent ) {
|
||||
if ( m_summary.hasRematchInfo() ) {
|
||||
titleID = R.string.waiting_rematch_title;
|
||||
message = getString( R.string.rematch_msg );
|
||||
} else {
|
||||
titleID = R.string.waiting_invite_title;
|
||||
message = getQuantityString( R.plurals.invite_sent_fmt,
|
||||
nSent, nSent, m_nMissing );
|
||||
}
|
||||
buttonTxt = R.string.button_reinvite;
|
||||
nukeNeutButton = false;
|
||||
} else if ( DeviceRole.SERVER_ISCLIENT == m_gi.serverRole ) {
|
||||
Assert.assertFalse( m_summary.hasRematchInfo() );
|
||||
message = getString( R.string.invited_msg );
|
||||
titleID = R.string.waiting_title;
|
||||
nukeInviteButton = true;
|
||||
} else {
|
||||
titleID = R.string.waiting_title;
|
||||
message = getQuantityString( R.plurals.invite_msg_fmt,
|
||||
m_nMissing, m_nMissing );
|
||||
}
|
||||
|
||||
if ( ! invitesSent && ! nukeInviteButton ) {
|
||||
String ps = null;
|
||||
if ( m_nMissing > 1 ) {
|
||||
ps = getString( R.string.invite_multiple );
|
||||
|
@ -519,19 +552,22 @@ public class BoardDelegate extends DelegateBase
|
|||
if ( null != ps ) {
|
||||
message += "\n\n" + ps;
|
||||
}
|
||||
|
||||
message += "\n\n" + getString( R.string.invite_stays );
|
||||
}
|
||||
|
||||
message += "\n\n" + getString( R.string.invite_stays );
|
||||
}
|
||||
|
||||
ad.setMessage( message );
|
||||
ad.setTitle( titleID );
|
||||
|
||||
Button posButton = ad.getButton( AlertDialog.BUTTON_POSITIVE );
|
||||
posButton.setVisibility( nukeButton ? View.GONE : View.VISIBLE );
|
||||
if ( !nukeButton ) {
|
||||
posButton.setText( buttonTxt );
|
||||
Button button = ad.getButton( AlertDialog.BUTTON_POSITIVE );
|
||||
button.setVisibility( nukeInviteButton ? View.GONE : View.VISIBLE );
|
||||
if ( !nukeInviteButton ) {
|
||||
button.setText( buttonTxt );
|
||||
}
|
||||
button = ad.getButton( AlertDialog.BUTTON_NEUTRAL );
|
||||
button.setVisibility( nukeNeutButton ? View.GONE : View.VISIBLE );
|
||||
|
||||
break;
|
||||
default:
|
||||
super.prepareDialog( dlgID, dialog );
|
||||
|
@ -687,7 +723,7 @@ public class BoardDelegate extends DelegateBase
|
|||
setBackgroundColor();
|
||||
setKeepScreenOn();
|
||||
} else if ( ! isFinishing() ) {
|
||||
if ( !m_relayConnected || 0 < m_nMissing ) {
|
||||
if ( m_relayMissing || 0 < m_nMissing ) {
|
||||
showDialog( DlgID.DLG_INVITE );
|
||||
}
|
||||
}
|
||||
|
@ -802,15 +838,16 @@ public class BoardDelegate extends DelegateBase
|
|||
enable = m_gameOver && rematchSupported( false );
|
||||
Utils.setItemVisible( menu, R.id.board_menu_rematch, enable );
|
||||
|
||||
enable = null != m_gi
|
||||
boolean netGame = null != m_gi
|
||||
&& DeviceRole.SERVER_STANDALONE != m_gi.serverRole;
|
||||
Utils.setItemVisible( menu, R.id.gamel_menu_checkmoves, enable );
|
||||
Utils.setItemVisible( menu, R.id.board_menu_game_resend,
|
||||
enable && null != m_gsi &&
|
||||
0 < m_gsi.nPendingMessages );
|
||||
Utils.setItemVisible( menu, R.id.gamel_menu_checkmoves, netGame );
|
||||
enable = netGame && null != m_gsi && 0 < m_gsi.nPendingMessages;
|
||||
Utils.setItemVisible( menu, R.id.board_menu_game_resend, enable );
|
||||
|
||||
enable = enable && BuildConfig.DEBUG;
|
||||
enable = netGame && (BuildConfig.DEBUG
|
||||
|| XWPrefs.getDebugEnabled( m_activity ) );
|
||||
Utils.setItemVisible( menu, R.id.board_menu_game_netstats, enable );
|
||||
Utils.setItemVisible( menu, R.id.board_menu_game_invites, enable );
|
||||
|
||||
enable = XWPrefs.getStudyEnabled( m_activity );
|
||||
Utils.setItemVisible( menu, R.id.games_menu_study, enable );
|
||||
|
@ -890,6 +927,10 @@ public class BoardDelegate extends DelegateBase
|
|||
case R.id.board_menu_game_netstats:
|
||||
m_jniThread.handle( JNICmd.CMD_NETSTATS, R.string.netstats_title );
|
||||
break;
|
||||
case R.id.board_menu_game_invites:
|
||||
SentInvitesInfo sentInfo = DBUtils.getInvitesFor( m_activity, m_rowid );
|
||||
showOKOnlyDialog( sentInfo.getAsText( m_activity ) );
|
||||
break;
|
||||
case R.id.board_menu_undo_current:
|
||||
cmd = JNICmd.CMD_UNDO_CUR;
|
||||
break;
|
||||
|
@ -950,7 +991,8 @@ public class BoardDelegate extends DelegateBase
|
|||
// DlgDelegate.DlgClickNotify interface
|
||||
//////////////////////////////////////////////////
|
||||
@Override
|
||||
public void dlgButtonClicked( Action action, int which, Object[] params )
|
||||
public void dlgButtonClicked( Action action, int which,
|
||||
final Object[] params )
|
||||
{
|
||||
boolean handled = false;
|
||||
if ( AlertDialog.BUTTON_POSITIVE == which ) {
|
||||
|
@ -1024,6 +1066,17 @@ public class BoardDelegate extends DelegateBase
|
|||
case DELETE_AND_EXIT:
|
||||
deleteAndClose();
|
||||
break;
|
||||
|
||||
case ENABLE_SMS_DO:
|
||||
handled = false; // so super gets called, before
|
||||
// retrySMSInvites
|
||||
post( new Runnable() {
|
||||
public void run() {
|
||||
retrySMSInvites( params );
|
||||
}
|
||||
} );
|
||||
break;
|
||||
|
||||
default:
|
||||
handled = false;
|
||||
}
|
||||
|
@ -1042,6 +1095,8 @@ public class BoardDelegate extends DelegateBase
|
|||
Object[] params )
|
||||
{
|
||||
if ( action == Action.LAUNCH_INVITE_ACTION ) {
|
||||
SentInvitesInfo info = params[0] instanceof SentInvitesInfo
|
||||
? (SentInvitesInfo)params[0] : null;
|
||||
switch( means ) {
|
||||
case NFC:
|
||||
if ( XWPrefs.getNFCToSelfEnabled( m_activity ) ) {
|
||||
|
@ -1053,11 +1108,11 @@ public class BoardDelegate extends DelegateBase
|
|||
}
|
||||
break;
|
||||
case BLUETOOTH:
|
||||
BTInviteDelegate.launchForResult( m_activity, m_nMissing,
|
||||
BTInviteDelegate.launchForResult( m_activity, m_nMissing, info,
|
||||
RequestCode.BT_INVITE_RESULT );
|
||||
break;
|
||||
case SMS:
|
||||
SMSInviteDelegate.launchForResult( m_activity, m_nMissing,
|
||||
SMSInviteDelegate.launchForResult( m_activity, m_nMissing, info,
|
||||
RequestCode.SMS_INVITE_RESULT );
|
||||
break;
|
||||
case RELAY:
|
||||
|
@ -1068,7 +1123,7 @@ public class BoardDelegate extends DelegateBase
|
|||
case CLIPBOARD:
|
||||
NetLaunchInfo nli = new NetLaunchInfo( m_summary, m_gi, 1,
|
||||
1 + m_nGuestDevs );
|
||||
if ( !m_relayConnected ) {
|
||||
if ( m_relayMissing ) {
|
||||
nli.removeAddress( CommsConnType.COMMS_CONN_RELAY );
|
||||
}
|
||||
if ( InviteMeans.EMAIL == means ) {
|
||||
|
@ -1076,6 +1131,8 @@ public class BoardDelegate extends DelegateBase
|
|||
} else if ( InviteMeans.CLIPBOARD == means ) {
|
||||
GameUtils.inviteURLToClip( m_activity, nli );
|
||||
}
|
||||
recordInviteSent( means, null );
|
||||
|
||||
break;
|
||||
default:
|
||||
Assert.fail();
|
||||
|
@ -1291,6 +1348,8 @@ public class BoardDelegate extends DelegateBase
|
|||
}
|
||||
if ( null != data ) {
|
||||
removeDialog( DlgID.CONFIRM_THEN );
|
||||
|
||||
recordInviteSent( InviteMeans.NFC, null );
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
@ -1475,7 +1534,7 @@ public class BoardDelegate extends DelegateBase
|
|||
}
|
||||
} else if ( nMissing > 0 ) {
|
||||
if ( m_summary.hasRematchInfo() ) {
|
||||
tryRematchInvites();
|
||||
tryRematchInvites( false );
|
||||
} else {
|
||||
if ( !m_haveInvited ) {
|
||||
m_haveInvited = true;
|
||||
|
@ -1818,7 +1877,7 @@ public class BoardDelegate extends DelegateBase
|
|||
m_nGuestDevs = nDevs;
|
||||
|
||||
// If we might have put up an alert earlier, take it down
|
||||
dismissInviteAlert( nMissing, m_relayConnected );
|
||||
dismissInviteAlert( nMissing, !m_relayMissing );
|
||||
|
||||
m_nMissing = nMissing; // will be 0 unless isServer is true
|
||||
|
||||
|
@ -1977,7 +2036,7 @@ public class BoardDelegate extends DelegateBase
|
|||
String langName = m_gi.langName();
|
||||
|
||||
m_summary = DBUtils.getSummary( m_activity, m_gameLock );
|
||||
m_relayConnected = !m_summary.relayConnectPending();
|
||||
m_relayMissing = m_summary.relayConnectPending();
|
||||
|
||||
setThis( this );
|
||||
|
||||
|
@ -2139,10 +2198,10 @@ public class BoardDelegate extends DelegateBase
|
|||
{
|
||||
runOnUiThread( new Runnable() {
|
||||
public void run() {
|
||||
if ( !m_relayConnected && connected ) {
|
||||
m_relayConnected = true;
|
||||
if ( m_relayMissing && connected ) {
|
||||
m_relayMissing = false;
|
||||
}
|
||||
if ( 0 == nMissing || m_relayConnected ) {
|
||||
if ( 0 == nMissing || !m_relayMissing ) {
|
||||
dismissDialog( DlgID.DLG_INVITE );
|
||||
}
|
||||
}
|
||||
|
@ -2370,7 +2429,7 @@ public class BoardDelegate extends DelegateBase
|
|||
private void tryInvites()
|
||||
{
|
||||
if ( 0 < m_nMissing && m_summary.hasRematchInfo() ) {
|
||||
tryRematchInvites();
|
||||
tryRematchInvites( false );
|
||||
} else if ( null != m_missingDevs ) {
|
||||
Assert.assertNotNull( m_missingMeans );
|
||||
String gameName = GameUtils.getName( m_activity, m_rowid );
|
||||
|
@ -2382,7 +2441,7 @@ public class BoardDelegate extends DelegateBase
|
|||
int forceChannel = ii + m_nGuestDevs + 1;
|
||||
NetLaunchInfo nli = new NetLaunchInfo( m_summary, m_gi,
|
||||
nPlayers, forceChannel );
|
||||
if ( !m_relayConnected ) {
|
||||
if ( m_relayMissing ) {
|
||||
nli.removeAddress( CommsConnType.COMMS_CONN_RELAY );
|
||||
}
|
||||
|
||||
|
@ -2403,7 +2462,8 @@ public class BoardDelegate extends DelegateBase
|
|||
BTService.inviteRemote( m_activity, dev, nli );
|
||||
break;
|
||||
case SMS:
|
||||
SMSService.inviteRemote( m_activity, dev, nli );
|
||||
sendSMSInviteIf( dev, nli, true );
|
||||
dev = null; // don't record send a second time
|
||||
break;
|
||||
case RELAY:
|
||||
try {
|
||||
|
@ -2415,6 +2475,10 @@ public class BoardDelegate extends DelegateBase
|
|||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if ( null != dev ) {
|
||||
recordInviteSent( m_missingMeans, dev );
|
||||
}
|
||||
}
|
||||
m_missingDevs = null;
|
||||
m_missingCounts = null;
|
||||
|
@ -2643,35 +2707,75 @@ public class BoardDelegate extends DelegateBase
|
|||
}
|
||||
}
|
||||
|
||||
private void tryRematchInvites()
|
||||
private void tryRematchInvites( boolean force )
|
||||
{
|
||||
if ( XWApp.REMATCH_SUPPORTED && !m_rematchInvitesSent ) {
|
||||
m_rematchInvitesSent = true;
|
||||
|
||||
Assert.assertNotNull( m_summary );
|
||||
Assert.assertNotNull( m_gi );
|
||||
// only supports a single invite for now!
|
||||
int numHere = 1;
|
||||
int forceChannel = 1;
|
||||
NetLaunchInfo nli = new NetLaunchInfo( m_summary, m_gi, numHere,
|
||||
forceChannel );
|
||||
|
||||
String value;
|
||||
value = m_summary.getStringExtra( GameSummary.EXTRA_REMATCH_PHONE );
|
||||
if ( null != value ) {
|
||||
SMSService.inviteRemote( m_activity, value, nli );
|
||||
if ( XWApp.REMATCH_SUPPORTED ) {
|
||||
if ( !force ) {
|
||||
SentInvitesInfo info = DBUtils.getInvitesFor( m_activity, m_rowid );
|
||||
force = 0 == info.getMinPlayerCount();
|
||||
}
|
||||
value = m_summary.getStringExtra( GameSummary.EXTRA_REMATCH_BTADDR );
|
||||
if ( null != value ) {
|
||||
BTService.inviteRemote( m_activity, value, nli );
|
||||
}
|
||||
value = m_summary.getStringExtra( GameSummary.EXTRA_REMATCH_RELAY );
|
||||
if ( null != value ) {
|
||||
RelayService.inviteRemote( m_activity, 0, value, nli );
|
||||
|
||||
if ( force ) {
|
||||
Assert.assertNotNull( m_summary );
|
||||
Assert.assertNotNull( m_gi );
|
||||
// only supports a single invite for now!
|
||||
int numHere = 1;
|
||||
int forceChannel = 1;
|
||||
NetLaunchInfo nli = new NetLaunchInfo( m_summary, m_gi, numHere,
|
||||
forceChannel );
|
||||
|
||||
String value;
|
||||
value = m_summary.getStringExtra( GameSummary.EXTRA_REMATCH_PHONE );
|
||||
if ( null != value ) {
|
||||
sendSMSInviteIf( value, nli, true );
|
||||
}
|
||||
value = m_summary.getStringExtra( GameSummary.EXTRA_REMATCH_BTADDR );
|
||||
if ( null != value ) {
|
||||
BTService.inviteRemote( m_activity, value, nli );
|
||||
recordInviteSent( InviteMeans.BLUETOOTH, value );
|
||||
}
|
||||
value = m_summary.getStringExtra( GameSummary.EXTRA_REMATCH_RELAY );
|
||||
if ( null != value ) {
|
||||
RelayService.inviteRemote( m_activity, 0, value, nli );
|
||||
recordInviteSent( InviteMeans.RELAY, value );
|
||||
}
|
||||
|
||||
showToast( R.string.rematch_sent_toast );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void sendSMSInviteIf( String phone, NetLaunchInfo nli,
|
||||
boolean askOk )
|
||||
{
|
||||
if ( XWPrefs.getSMSEnabled( m_activity ) ) {
|
||||
SMSService.inviteRemote( m_activity, phone, nli );
|
||||
recordInviteSent( InviteMeans.SMS, phone );
|
||||
} else if ( askOk ) {
|
||||
showConfirmThen( R.string.warn_sms_disabled,
|
||||
R.string.button_enable_sms,
|
||||
R.string.button_later,
|
||||
Action.ENABLE_SMS_ASK, nli, phone );
|
||||
}
|
||||
}
|
||||
|
||||
private void retrySMSInvites( Object[] params )
|
||||
{
|
||||
if ( null != params && 2 == params.length
|
||||
&& params[0] instanceof NetLaunchInfo
|
||||
&& params[1] instanceof String ) {
|
||||
sendSMSInviteIf( (String)params[1], (NetLaunchInfo)params[0],
|
||||
false );
|
||||
} else {
|
||||
DbgUtils.logf( "retrySMSInvites: tests failed" );
|
||||
}
|
||||
}
|
||||
|
||||
private void recordInviteSent( InviteMeans means, String dev )
|
||||
{
|
||||
DBUtils.recordInviteSent( m_activity, m_rowid, means, dev );
|
||||
}
|
||||
|
||||
private static void noteSkip()
|
||||
{
|
||||
String msg = "BoardActivity.feedMessage[s](): skipped because "
|
||||
|
|
|
@ -41,8 +41,9 @@ public class DBHelper extends SQLiteOpenHelper {
|
|||
public static final String TABLE_NAME_STUDYLIST = "study";
|
||||
public static final String TABLE_NAME_LOC = "loc";
|
||||
public static final String TABLE_NAME_PAIRS = "pairs";
|
||||
public static final String TABLE_NAME_INVITES = "invites";
|
||||
private static final String DB_NAME = "xwdb";
|
||||
private static final int DB_VERSION = 24;
|
||||
private static final int DB_VERSION = 25;
|
||||
|
||||
public static final String GAME_NAME = "GAME_NAME";
|
||||
public static final String VISID = "VISID";
|
||||
|
@ -69,7 +70,8 @@ public class DBHelper extends SQLiteOpenHelper {
|
|||
public static final String CONTYPE = "CONTYPE";
|
||||
public static final String SERVERROLE = "SERVERROLE";
|
||||
public static final String ROOMNAME = "ROOMNAME";
|
||||
public static final String INVITEID = "INVITEID";
|
||||
// written but never read; can go away
|
||||
// public static final String INVITEID = "INVITEID";
|
||||
public static final String RELAYID = "RELAYID";
|
||||
public static final String SEED = "SEED";
|
||||
public static final String SMSPHONE = "SMSPHONE"; // unused -- so far
|
||||
|
@ -104,6 +106,10 @@ public class DBHelper extends SQLiteOpenHelper {
|
|||
public static final String BLESSED = "BLESSED";
|
||||
public static final String XLATION = "XLATION";
|
||||
|
||||
public static final String ROW = "ROW";
|
||||
public static final String MEANS = "MEANS";
|
||||
public static final String TARGET = "TARGET";
|
||||
public static final String TIMESTAMP = "TIMESTAMP";
|
||||
|
||||
private Context m_context;
|
||||
|
||||
|
@ -121,7 +127,6 @@ public class DBHelper extends SQLiteOpenHelper {
|
|||
,{ SERVERROLE, "INTEGER" }
|
||||
,{ CONTYPE, "INTEGER" }
|
||||
,{ ROOMNAME, "TEXT" }
|
||||
,{ INVITEID, "TEXT" }
|
||||
,{ RELAYID, "TEXT" }
|
||||
,{ SEED, "INTEGER" }
|
||||
,{ DICTLANG, "INTEGER" }
|
||||
|
@ -194,6 +199,13 @@ public class DBHelper extends SQLiteOpenHelper {
|
|||
,{ "UNIQUE", "(" + KEY + ")" }
|
||||
};
|
||||
|
||||
private static final String[][] s_invitesSchema = {
|
||||
{ ROW, "INTEGER" }
|
||||
,{ TARGET, "TEXT" }
|
||||
,{ MEANS, "INTEGER" }
|
||||
,{ TIMESTAMP, "DATETIME DEFAULT CURRENT_TIMESTAMP" }
|
||||
};
|
||||
|
||||
public DBHelper( Context context )
|
||||
{
|
||||
super( context, DB_NAME, null, DB_VERSION );
|
||||
|
@ -217,6 +229,7 @@ public class DBHelper extends SQLiteOpenHelper {
|
|||
createStudyTable( db );
|
||||
createLocTable( db );
|
||||
createPairsTable( db );
|
||||
createInvitesTable( db );
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -241,7 +254,6 @@ public class DBHelper extends SQLiteOpenHelper {
|
|||
case 9:
|
||||
addSumColumn( db, DICTLIST );
|
||||
case 10:
|
||||
addSumColumn( db, INVITEID );
|
||||
case 11:
|
||||
addSumColumn( db, REMOTEDEVS );
|
||||
case 12:
|
||||
|
@ -283,6 +295,9 @@ public class DBHelper extends SQLiteOpenHelper {
|
|||
if ( !madeSumTable ) {
|
||||
addSumColumn( db, EXTRAS );
|
||||
}
|
||||
case 24:
|
||||
createInvitesTable( db );
|
||||
|
||||
break;
|
||||
default:
|
||||
db.execSQL( "DROP TABLE " + TABLE_NAME_SUM + ";" );
|
||||
|
@ -381,6 +396,11 @@ public class DBHelper extends SQLiteOpenHelper {
|
|||
createTable( db, TABLE_NAME_PAIRS, s_pairsSchema );
|
||||
}
|
||||
|
||||
private void createInvitesTable( SQLiteDatabase db )
|
||||
{
|
||||
createTable( db, TABLE_NAME_INVITES, s_invitesSchema );
|
||||
}
|
||||
|
||||
// Move all existing games to the row previously named "cur games'
|
||||
private void moveToCurGames( SQLiteDatabase db )
|
||||
{
|
||||
|
|
|
@ -34,6 +34,8 @@ import android.net.Uri;
|
|||
import android.os.Environment;
|
||||
import android.text.TextUtils;
|
||||
|
||||
import java.sql.Timestamp;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
|
@ -52,10 +54,11 @@ import java.util.Set;
|
|||
import java.util.StringTokenizer;
|
||||
import junit.framework.Assert;
|
||||
|
||||
import org.eehouse.android.xw4.DictUtils.DictLoc;
|
||||
import org.eehouse.android.xw4.DlgDelegate.DlgClickNotify.InviteMeans;
|
||||
import org.eehouse.android.xw4.jni.*;
|
||||
import org.eehouse.android.xw4.jni.CommsAddrRec.CommsConnType;
|
||||
import org.eehouse.android.xw4.jni.CommsAddrRec.CommsConnTypeSet;
|
||||
import org.eehouse.android.xw4.DictUtils.DictLoc;
|
||||
import org.eehouse.android.xw4.loc.LocUtils;
|
||||
|
||||
public class DBUtils {
|
||||
|
@ -268,12 +271,6 @@ public class DBUtils {
|
|||
|
||||
public static void saveSummary( Context context, GameLock lock,
|
||||
GameSummary summary )
|
||||
{
|
||||
saveSummary( context, lock, summary, null );
|
||||
}
|
||||
|
||||
public static void saveSummary( Context context, GameLock lock,
|
||||
GameSummary summary, String inviteID )
|
||||
{
|
||||
boolean needsTimer = false;
|
||||
Assert.assertTrue( lock.canWrite() );
|
||||
|
@ -294,7 +291,15 @@ public class DBUtils {
|
|||
values.put( DBHelper.GAMEID, summary.gameID );
|
||||
values.put( DBHelper.GAME_OVER, summary.gameOver? 1 : 0 );
|
||||
values.put( DBHelper.LASTMOVE, summary.lastMoveTime );
|
||||
values.put( DBHelper.EXTRAS, summary.getExtras() );
|
||||
|
||||
// Don't overwrite extras! Sometimes this method is called from
|
||||
// JNIThread which has created the summary from common code that
|
||||
// doesn't know about Android additions. Leave those unset to
|
||||
// avoid overwriting.
|
||||
String extras = summary.getExtras();
|
||||
if ( null != extras ) {
|
||||
values.put( DBHelper.EXTRAS, summary.getExtras() );
|
||||
}
|
||||
long nextNag = summary.nextTurnIsLocal() ?
|
||||
NagTurnReceiver.figureNextNag( context,
|
||||
1000*(long)summary.lastMoveTime )
|
||||
|
@ -302,9 +307,6 @@ public class DBUtils {
|
|||
values.put( DBHelper.NEXTNAG, nextNag );
|
||||
|
||||
values.put( DBHelper.DICTLIST, summary.dictNames(DICTS_SEP) );
|
||||
if ( null != inviteID ) {
|
||||
values.put( DBHelper.INVITEID, inviteID );
|
||||
}
|
||||
|
||||
if ( null != summary.scores ) {
|
||||
StringBuffer sb = new StringBuffer();
|
||||
|
@ -426,6 +428,172 @@ public class DBUtils {
|
|||
return result;
|
||||
}
|
||||
|
||||
public static class SentInvitesInfo {
|
||||
public long m_rowid;
|
||||
private ArrayList<InviteMeans> m_means;
|
||||
private ArrayList<String> m_targets;
|
||||
private ArrayList<Timestamp> m_timestamps;
|
||||
private int m_cachedCount = 0;
|
||||
|
||||
private SentInvitesInfo( long rowID ) {
|
||||
m_rowid = rowID;
|
||||
m_means = new ArrayList<InviteMeans>();
|
||||
m_targets = new ArrayList<String>();
|
||||
m_timestamps = new ArrayList<Timestamp>();
|
||||
}
|
||||
|
||||
private void addEntry( InviteMeans means, String target, Timestamp ts )
|
||||
{
|
||||
m_means.add( means );
|
||||
m_targets.add( target );
|
||||
m_timestamps.add( ts );
|
||||
m_cachedCount = -1;
|
||||
}
|
||||
|
||||
public InviteMeans getLastMeans()
|
||||
{
|
||||
return 0 < m_means.size() ? m_means.get(0) : null;
|
||||
}
|
||||
|
||||
public String getLastDev( InviteMeans means )
|
||||
{
|
||||
String result = null;
|
||||
for ( int ii = 0; null == result && ii < m_means.size(); ++ii ) {
|
||||
if ( means == m_means.get( ii ) ) {
|
||||
result = m_targets.get( ii );
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
// There will be lots of duplicates, but we can't detect them all. BUT
|
||||
// if means and target are the same it's definitely a dup. So count
|
||||
// them all and return the largest number we have. 99% of the time we
|
||||
// care only that it's non-0.
|
||||
public int getMinPlayerCount() {
|
||||
if ( -1 == m_cachedCount ) {
|
||||
DbgUtils.logf( "getMinPlayerCount(%H)", this );
|
||||
int count = m_timestamps.size();
|
||||
Map<InviteMeans, Set<String>> hashes
|
||||
= new HashMap<InviteMeans, Set<String>>();
|
||||
int fakeCount = 0; // make all null-targets count for one
|
||||
for ( int ii = 0; ii < count; ++ii ) {
|
||||
InviteMeans means = m_means.get(ii);
|
||||
Set<String> devs;
|
||||
if ( ! hashes.containsKey( means ) ) {
|
||||
DbgUtils.logf( "creating new hash for means %s", means.toString() );
|
||||
devs = new HashSet<String>();
|
||||
hashes.put( means, devs );
|
||||
}
|
||||
devs = hashes.get( means );
|
||||
String target = m_targets.get( ii );
|
||||
if ( null == target ) {
|
||||
target = String.format( "%d", ++fakeCount );
|
||||
}
|
||||
devs.add( target );
|
||||
DbgUtils.logf( "added target %s for means %s", target, means.toString() );
|
||||
}
|
||||
|
||||
// Now find the max
|
||||
m_cachedCount = 0;
|
||||
for ( InviteMeans means : InviteMeans.values() ) {
|
||||
if ( hashes.containsKey( means ) ) {
|
||||
int siz = hashes.get( means ).size();
|
||||
m_cachedCount += siz;
|
||||
DbgUtils.logf( "counting: means %s has unique count of %d",
|
||||
means.toString(), siz );
|
||||
}
|
||||
}
|
||||
}
|
||||
DbgUtils.logf( "getMinPlayerCount(%H) => %d", this, m_cachedCount );
|
||||
return m_cachedCount;
|
||||
}
|
||||
|
||||
public String getAsText( Context context )
|
||||
{
|
||||
int count = m_timestamps.size();
|
||||
String[] strs = new String[count];
|
||||
for ( int ii = 0; ii < count; ++ii ) {
|
||||
InviteMeans means = m_means.get(ii);
|
||||
String target = m_targets.get(ii);
|
||||
String timestamp = m_timestamps.get(ii).toString();
|
||||
String msg;
|
||||
|
||||
switch ( means ) {
|
||||
case SMS:
|
||||
msg = LocUtils.getString( context, R.string.invit_expl_sms_fmt,
|
||||
target, timestamp );
|
||||
break;
|
||||
case BLUETOOTH:
|
||||
String devName = BTService.nameForAddr( target );
|
||||
msg = LocUtils.getString( context, R.string.invit_expl_bt_fmt,
|
||||
devName, timestamp );
|
||||
break;
|
||||
case RELAY:
|
||||
msg = LocUtils.getString( context, R.string.invit_expl_relay_fmt,
|
||||
timestamp );
|
||||
break;
|
||||
default:
|
||||
msg = LocUtils.getString( context, R.string.invit_expl_notarget_fmt,
|
||||
means.toString(), timestamp );
|
||||
|
||||
}
|
||||
strs[ii] = msg;
|
||||
}
|
||||
return TextUtils.join( "\n\n", strs );
|
||||
}
|
||||
}
|
||||
|
||||
public static SentInvitesInfo getInvitesFor( Context context, long rowid )
|
||||
{
|
||||
SentInvitesInfo result = new SentInvitesInfo( rowid );
|
||||
|
||||
String[] columns = { DBHelper.MEANS, DBHelper.TIMESTAMP, DBHelper.TARGET };
|
||||
String selection = String.format( "%s = %d", DBHelper.ROW, rowid );
|
||||
String orderBy = DBHelper.TIMESTAMP + " DESC";
|
||||
|
||||
synchronized( s_dbHelper ) {
|
||||
SQLiteDatabase db = s_dbHelper.getReadableDatabase();
|
||||
Cursor cursor = db.query( DBHelper.TABLE_NAME_INVITES, columns,
|
||||
selection, null, null, null, orderBy );
|
||||
if ( 0 < cursor.getCount() ) {
|
||||
int indxMns = cursor.getColumnIndex( DBHelper.MEANS );
|
||||
int indxTS = cursor.getColumnIndex( DBHelper.TIMESTAMP );
|
||||
int indxTrgt = cursor.getColumnIndex( DBHelper.TARGET );
|
||||
|
||||
while ( cursor.moveToNext() ) {
|
||||
InviteMeans means = InviteMeans.values()[cursor.getInt( indxMns )];
|
||||
Timestamp ts = Timestamp.valueOf(cursor.getString(indxTS));
|
||||
String target = cursor.getString( indxTrgt );
|
||||
result.addEntry( means, target, ts );
|
||||
}
|
||||
}
|
||||
cursor.close();
|
||||
db.close();
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public static void recordInviteSent( Context context, long rowid,
|
||||
InviteMeans means, String target )
|
||||
{
|
||||
ContentValues values = new ContentValues();
|
||||
values.put( DBHelper.ROW, rowid );
|
||||
values.put( DBHelper.MEANS, means.ordinal() );
|
||||
if ( null != target ) {
|
||||
values.put( DBHelper.TARGET, target );
|
||||
}
|
||||
|
||||
initDB( context );
|
||||
synchronized( s_dbHelper ) {
|
||||
SQLiteDatabase db = s_dbHelper.getWritableDatabase();
|
||||
db.insert( DBHelper.TABLE_NAME_INVITES, null, values );
|
||||
db.close();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static void setInt( long rowid, String column, int value )
|
||||
{
|
||||
ContentValues values = new ContentValues();
|
||||
|
@ -938,11 +1106,17 @@ public class DBUtils {
|
|||
public static void deleteGame( Context context, GameLock lock )
|
||||
{
|
||||
Assert.assertTrue( lock.canWrite() );
|
||||
String selection = String.format( ROW_ID_FMT, lock.getRowid() );
|
||||
String selSummaries = String.format( ROW_ID_FMT, lock.getRowid() );
|
||||
String selInvites = String.format( "%s=%d", DBHelper.ROW, lock.getRowid() );
|
||||
|
||||
initDB( context );
|
||||
synchronized( s_dbHelper ) {
|
||||
SQLiteDatabase db = s_dbHelper.getWritableDatabase();
|
||||
db.delete( DBHelper.TABLE_NAME_SUM, selection, null );
|
||||
db.delete( DBHelper.TABLE_NAME_SUM, selSummaries, null );
|
||||
|
||||
// Delete invitations too
|
||||
db.delete( DBHelper.TABLE_NAME_INVITES, selInvites, null );
|
||||
|
||||
db.close();
|
||||
}
|
||||
notifyListeners( lock.getRowid(), GameChangeType.GAME_DELETED );
|
||||
|
|
|
@ -426,6 +426,12 @@ public class DelegateBase implements DlgClickNotify,
|
|||
m_dlgDelegate.showConfirmThen( msg, posButton, negButton, action );
|
||||
}
|
||||
|
||||
protected void showConfirmThen( int msg, int posButton, int negButton,
|
||||
Action action, Object... params )
|
||||
{
|
||||
m_dlgDelegate.showConfirmThen( msg, posButton, negButton, action, params );
|
||||
}
|
||||
|
||||
protected void showConfirmThen( int msg, int posButton, Action action,
|
||||
Object... params )
|
||||
{
|
||||
|
@ -465,9 +471,10 @@ public class DelegateBase implements DlgClickNotify,
|
|||
m_dlgDelegate.launchLookup( words, lang, !studyOn );
|
||||
}
|
||||
|
||||
protected void showInviteChoicesThen( Action action )
|
||||
protected void showInviteChoicesThen( Action action,
|
||||
DBUtils.SentInvitesInfo info )
|
||||
{
|
||||
m_dlgDelegate.showInviteChoicesThen( action );
|
||||
m_dlgDelegate.showInviteChoicesThen( action, info );
|
||||
}
|
||||
|
||||
protected void showOKOnlyDialogThen( String msg, Action action )
|
||||
|
@ -512,9 +519,9 @@ public class DelegateBase implements DlgClickNotify,
|
|||
m_dlgDelegate.showDictGoneFinish();
|
||||
}
|
||||
|
||||
protected void showSMSEnableDialog( Action action )
|
||||
protected void showSMSEnableDialog( Action action, Object... params )
|
||||
{
|
||||
m_dlgDelegate.showSMSEnableDialog( action );
|
||||
m_dlgDelegate.showSMSEnableDialog( action, params );
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////
|
||||
|
@ -565,14 +572,11 @@ public class DelegateBase implements DlgClickNotify,
|
|||
if ( AlertDialog.BUTTON_POSITIVE == button ) {
|
||||
switch( action ) {
|
||||
case ENABLE_SMS_ASK:
|
||||
showSMSEnableDialog( Action.ENABLE_SMS_DO );
|
||||
showSMSEnableDialog( Action.ENABLE_SMS_DO, params );
|
||||
handled = true;
|
||||
break;
|
||||
case ENABLE_SMS_DO:
|
||||
boolean enabled = (Boolean)params[0];
|
||||
if ( enabled ) {
|
||||
XWPrefs.setSMSEnabled( m_activity, true );
|
||||
}
|
||||
XWPrefs.setSMSEnabled( m_activity, true );
|
||||
break;
|
||||
case ENABLE_BT_DO:
|
||||
BTService.enable();
|
||||
|
|
|
@ -304,7 +304,10 @@ public class DictUtils {
|
|||
|
||||
public static void deleteDict( Context context, String name )
|
||||
{
|
||||
deleteDict( context, name, getDictLoc( context, name ) );
|
||||
DictLoc loc = getDictLoc( context, name );
|
||||
if ( null != loc ) {
|
||||
deleteDict( context, name, getDictLoc(context, name) );
|
||||
}
|
||||
}
|
||||
|
||||
private static byte[] openDict( Context context, String name, DictLoc loc )
|
||||
|
|
|
@ -47,6 +47,7 @@ import java.util.Iterator;
|
|||
import junit.framework.Assert;
|
||||
|
||||
import org.eehouse.android.xw4.loc.LocUtils;
|
||||
import org.eehouse.android.xw4.DBUtils.SentInvitesInfo;
|
||||
|
||||
public class DlgDelegate {
|
||||
|
||||
|
@ -138,6 +139,8 @@ public class DlgDelegate {
|
|||
private static final String STATE_KEYF = "STATE_%d";
|
||||
|
||||
public interface DlgClickNotify {
|
||||
// These are stored in the INVITES table. Don't change order
|
||||
// gratuitously
|
||||
public static enum InviteMeans {
|
||||
SMS, EMAIL, NFC, BLUETOOTH, CLIPBOARD, RELAY,
|
||||
};
|
||||
|
@ -280,9 +283,9 @@ public class DlgDelegate {
|
|||
// Puts up alert asking to choose a reason to enable SMS, and on dismiss
|
||||
// calls dlgButtonClicked with the action and in params a Boolean
|
||||
// indicating whether enabling is now ok.
|
||||
public void showSMSEnableDialog( Action action )
|
||||
public void showSMSEnableDialog( Action action, Object... params )
|
||||
{
|
||||
DlgState state = new DlgState( DlgID.DIALOG_ENABLESMS, action );
|
||||
DlgState state = new DlgState( DlgID.DIALOG_ENABLESMS, action, params );
|
||||
addState( state );
|
||||
showDialog( DlgID.DIALOG_ENABLESMS );
|
||||
}
|
||||
|
@ -366,6 +369,12 @@ public class DlgDelegate {
|
|||
showConfirmThen( null, getString(msg), posButton, negButton, action, null );
|
||||
}
|
||||
|
||||
public void showConfirmThen( int msg, int posButton, int negButton, Action action,
|
||||
Object... params )
|
||||
{
|
||||
showConfirmThen( null, getString(msg), posButton, negButton, action, params );
|
||||
}
|
||||
|
||||
public void showConfirmThen( int msg, int posButton, Action action,
|
||||
Object[] params )
|
||||
{
|
||||
|
@ -389,13 +398,14 @@ public class DlgDelegate {
|
|||
showDialog( DlgID.CONFIRM_THEN );
|
||||
}
|
||||
|
||||
public void showInviteChoicesThen( final Action action )
|
||||
public void showInviteChoicesThen( final Action action,
|
||||
SentInvitesInfo info )
|
||||
{
|
||||
if ( (XWApp.SMS_INVITE_ENABLED && Utils.deviceSupportsSMS( m_activity ))
|
||||
|| XWPrefs.getNFCToSelfEnabled( m_activity )
|
||||
|| NFCUtils.nfcAvail( m_activity )[0]
|
||||
|| BTService.BTAvailable() ) {
|
||||
DlgState state = new DlgState( DlgID.INVITE_CHOICES_THEN, action );
|
||||
DlgState state = new DlgState( DlgID.INVITE_CHOICES_THEN, action, info );
|
||||
addState( state );
|
||||
showDialog( DlgID.INVITE_CHOICES_THEN );
|
||||
} else {
|
||||
|
@ -614,6 +624,12 @@ public class DlgDelegate {
|
|||
final ArrayList<DlgClickNotify.InviteMeans> means =
|
||||
new ArrayList<DlgClickNotify.InviteMeans>();
|
||||
ArrayList<String> items = new ArrayList<String>();
|
||||
DlgClickNotify.InviteMeans lastMeans = null;
|
||||
if ( null != state.m_params
|
||||
&& state.m_params[0] instanceof SentInvitesInfo ) {
|
||||
lastMeans =((SentInvitesInfo)state.m_params[0]).getLastMeans();
|
||||
}
|
||||
|
||||
if ( XWApp.SMS_INVITE_ENABLED && Utils.deviceSupportsSMS(m_activity) ) {
|
||||
items.add( getString( R.string.invite_choice_sms ) );
|
||||
means.add( DlgClickNotify.InviteMeans.SMS );
|
||||
|
@ -633,27 +649,41 @@ public class DlgDelegate {
|
|||
items.add( getString( R.string.invite_choice_relay ) );
|
||||
means.add( DlgClickNotify.InviteMeans.RELAY );
|
||||
}
|
||||
final int clipPos = means.size();
|
||||
items.add( getString( R.string.slmenu_copy_sel ) );
|
||||
means.add( DlgClickNotify.InviteMeans.CLIPBOARD );
|
||||
|
||||
final int[] sel = { -1 };
|
||||
if ( null != lastMeans ) {
|
||||
for ( int ii = 0; ii < means.size(); ++ii ) {
|
||||
if ( lastMeans == means.get(ii) ) {
|
||||
sel[0] = ii;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
OnClickListener selChanged = new OnClickListener() {
|
||||
public void onClick( DialogInterface dlg, int view ) {
|
||||
// First time through, enable the button
|
||||
if ( -1 == sel[0] ) {
|
||||
((AlertDialog)dlg)
|
||||
.getButton( AlertDialog.BUTTON_POSITIVE )
|
||||
.setEnabled( true );
|
||||
}
|
||||
sel[0] = view;
|
||||
|
||||
if ( view == clipPos ) {
|
||||
switch ( means.get(view) ) {
|
||||
case CLIPBOARD:
|
||||
String msg =
|
||||
getString( R.string.not_again_clip_expl_fmt,
|
||||
getString(R.string.slmenu_copy_sel) );
|
||||
showNotAgainDlgThen( msg, R.string.key_na_clip_expl );
|
||||
break;
|
||||
case SMS:
|
||||
if ( ! XWPrefs.getSMSEnabled( m_activity ) ) {
|
||||
showConfirmThen( R.string.warn_sms_disabled,
|
||||
R.string.button_enable_sms,
|
||||
R.string.button_later,
|
||||
Action.ENABLE_SMS_ASK );
|
||||
}
|
||||
break;
|
||||
}
|
||||
Button button = ((AlertDialog)dlg)
|
||||
.getButton( AlertDialog.BUTTON_POSITIVE );
|
||||
button.setEnabled( true );
|
||||
}
|
||||
};
|
||||
OnClickListener okClicked = new OnClickListener() {
|
||||
|
@ -670,7 +700,7 @@ public class DlgDelegate {
|
|||
|
||||
AlertDialog.Builder builder = LocUtils.makeAlertBuilder( m_activity )
|
||||
.setTitle( R.string.invite_choice_title )
|
||||
.setSingleChoiceItems( items.toArray( new String[items.size()] ),
|
||||
.setSingleChoiceItems( items.toArray( new String[items.size()] ),
|
||||
sel[0], selChanged )
|
||||
.setPositiveButton( android.R.string.ok, okClicked )
|
||||
.setNegativeButton( android.R.string.cancel, null );
|
||||
|
@ -683,7 +713,8 @@ public class DlgDelegate {
|
|||
AlertDialog ad = (AlertDialog)dialog;
|
||||
Button button = ad.getButton( AlertDialog.BUTTON_POSITIVE );
|
||||
if ( null != button ) {
|
||||
button.setEnabled( false );
|
||||
long[] ids = ad.getListView().getCheckedItemIds();
|
||||
button.setEnabled( 1 == ids.length );
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -715,10 +746,9 @@ public class DlgDelegate {
|
|||
layout.findViewById( R.id.confirm_sms_reasons );
|
||||
boolean enabled = 0 < reasons.getSelectedItemPosition();
|
||||
Assert.assertTrue( enabled );
|
||||
Object[] params = { new Boolean(enabled), };
|
||||
m_clickCallback.dlgButtonClicked( state.m_action,
|
||||
AlertDialog.BUTTON_POSITIVE,
|
||||
params );
|
||||
state.m_params );
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -91,6 +91,11 @@ public class DlgState implements Parcelable {
|
|||
this( dlgID, null, 0, null, 0, params );
|
||||
}
|
||||
|
||||
public DlgState( DlgID dlgID, Action action, Object... params )
|
||||
{
|
||||
this( dlgID, null, 0, action, 0, params );
|
||||
}
|
||||
|
||||
public int describeContents() {
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -391,6 +391,15 @@ public class DwnldDelegate extends ListDelegateBase {
|
|||
downloadDictInBack( context, uri, name, lstnr );
|
||||
}
|
||||
|
||||
public static void downloadDictInBack( Context context, Uri uri,
|
||||
String name,
|
||||
DownloadFinishedListener lstnr )
|
||||
{
|
||||
Uri[] uris = new Uri[] { uri };
|
||||
String[] names = new String[] { name };
|
||||
downloadDictsInBack( context, uris, names, lstnr );
|
||||
}
|
||||
|
||||
public static void downloadDictsInBack( Context context, Uri[] uris,
|
||||
String[] names,
|
||||
DownloadFinishedListener lstnr )
|
||||
|
@ -406,15 +415,6 @@ public class DwnldDelegate extends ListDelegateBase {
|
|||
context.startActivity( intent );
|
||||
}
|
||||
|
||||
public static void downloadDictInBack( Context context, Uri uri,
|
||||
String name,
|
||||
DownloadFinishedListener lstnr )
|
||||
{
|
||||
Uri[] uris = new Uri[] { uri };
|
||||
String[] names = new String[] { name };
|
||||
downloadDictsInBack( context, uris, names, lstnr );
|
||||
}
|
||||
|
||||
public static Intent makeAppDownloadIntent( Context context, String url )
|
||||
{
|
||||
Intent intent = new Intent( context, DwnldActivity.class );
|
||||
|
|
|
@ -102,6 +102,12 @@ public class GameListItem extends LinearLayout
|
|||
} );
|
||||
}
|
||||
|
||||
public GameSummary getSummary()
|
||||
{
|
||||
Assert.assertNotNull( m_summary );
|
||||
return m_summary;
|
||||
}
|
||||
|
||||
private void init( Handler handler, long rowid, int fieldID,
|
||||
SelectableItem cb )
|
||||
{
|
||||
|
@ -320,7 +326,7 @@ public class GameListItem extends LinearLayout
|
|||
}
|
||||
} );
|
||||
|
||||
String roleSummary = summary.summarizeRole();
|
||||
String roleSummary = summary.summarizeRole( m_rowid );
|
||||
if ( null != roleSummary ) {
|
||||
m_role.setText( roleSummary );
|
||||
} else {
|
||||
|
|
|
@ -469,8 +469,8 @@ public class GameUtils {
|
|||
addr, new int[] {nli.lang},
|
||||
new String[] { nli.dict }, nli.nPlayersT,
|
||||
nli.nPlayersH, nli.forceChannel,
|
||||
nli.inviteID(), nli.gameID(), nli.gameName,
|
||||
false );
|
||||
nli.inviteID(), nli.gameID(),
|
||||
nli.gameName, false );
|
||||
}
|
||||
|
||||
public static long makeNewMultiGame( Context context, long groupID,
|
||||
|
@ -543,7 +543,7 @@ public class GameUtils {
|
|||
|
||||
if ( DBUtils.ROWID_NOTFOUND != rowid ) {
|
||||
GameLock lock = new GameLock( rowid, true ).lock();
|
||||
applyChanges( context, sink, gi, util, addr, inviteID, lock, false );
|
||||
applyChanges( context, sink, gi, util, addr, lock, false );
|
||||
lock.unlock();
|
||||
}
|
||||
|
||||
|
@ -875,7 +875,8 @@ public class GameUtils {
|
|||
|
||||
public static boolean feedMessages( Context context, long rowid,
|
||||
byte[][] msgs, CommsAddrRec ret,
|
||||
MultiMsgSink sink, BackMoveResult bmr )
|
||||
MultiMsgSink sink, BackMoveResult bmr,
|
||||
boolean[] isLocalOut )
|
||||
{
|
||||
boolean draw = false;
|
||||
Assert.assertTrue( -1 != rowid );
|
||||
|
@ -920,7 +921,12 @@ public class GameUtils {
|
|||
}
|
||||
|
||||
saveGame( context, gamePtr, gi, lock, false );
|
||||
summarizeAndClose( context, lock, gamePtr, gi );
|
||||
GameSummary summary = summarizeAndClose( context, lock,
|
||||
gamePtr, gi );
|
||||
if ( null != isLocalOut ) {
|
||||
isLocalOut[0] = 0 <= summary.turn
|
||||
&& gi.players[summary.turn].isLocal;
|
||||
}
|
||||
|
||||
int flags = setFromFeedImpl( feedImpl );
|
||||
if ( GameSummary.MSG_FLAGS_NONE != flags ) {
|
||||
|
@ -937,12 +943,12 @@ public class GameUtils {
|
|||
|
||||
public static boolean feedMessage( Context context, long rowid, byte[] msg,
|
||||
CommsAddrRec ret, MultiMsgSink sink,
|
||||
BackMoveResult bmr )
|
||||
BackMoveResult bmr, boolean[] isLocalOut )
|
||||
{
|
||||
Assert.assertTrue( DBUtils.ROWID_NOTFOUND != rowid );
|
||||
byte[][] msgs = new byte[1][];
|
||||
msgs[0] = msg;
|
||||
return feedMessages( context, rowid, msgs, ret, sink, bmr );
|
||||
return feedMessages( context, rowid, msgs, ret, sink, bmr, isLocalOut );
|
||||
}
|
||||
|
||||
// This *must* involve a reset if the language is changing!!!
|
||||
|
@ -986,24 +992,17 @@ public class GameUtils {
|
|||
} // replaceDicts
|
||||
|
||||
public static void applyChanges( Context context, CurGameInfo gi,
|
||||
CommsAddrRec car, GameLock lock,
|
||||
CommsAddrRec car, GameLock lock,
|
||||
boolean forceNew )
|
||||
{
|
||||
applyChanges( context, gi, car, null, lock, forceNew );
|
||||
}
|
||||
|
||||
public static void applyChanges( Context context, CurGameInfo gi,
|
||||
CommsAddrRec car, String inviteID,
|
||||
GameLock lock, boolean forceNew )
|
||||
{
|
||||
applyChanges( context, (MultiMsgSink)null, gi, (UtilCtxt)null, car,
|
||||
inviteID, lock, forceNew );
|
||||
lock, forceNew );
|
||||
}
|
||||
|
||||
public static void applyChanges( Context context, MultiMsgSink sink,
|
||||
CurGameInfo gi, UtilCtxt util,
|
||||
CommsAddrRec car, String inviteID,
|
||||
GameLock lock, boolean forceNew )
|
||||
CommsAddrRec car, GameLock lock,
|
||||
boolean forceNew )
|
||||
{
|
||||
// This should be a separate function, commitChanges() or
|
||||
// somesuch. But: do we have a way to save changes to a gi
|
||||
|
@ -1049,7 +1048,7 @@ public class GameUtils {
|
|||
|
||||
GameSummary summary = new GameSummary( context, gi );
|
||||
XwJNI.game_summarize( gamePtr, summary );
|
||||
DBUtils.saveSummary( context, lock, summary, inviteID );
|
||||
DBUtils.saveSummary( context, lock, summary );
|
||||
|
||||
XwJNI.game_dispose( gamePtr );
|
||||
} // applyChanges
|
||||
|
@ -1086,7 +1085,8 @@ public class GameUtils {
|
|||
}
|
||||
|
||||
public static void postMoveNotification( Context context, long rowid,
|
||||
BackMoveResult bmr )
|
||||
BackMoveResult bmr,
|
||||
boolean isTurnNow )
|
||||
{
|
||||
if ( null != bmr ) {
|
||||
Intent intent = GamesListDelegate.makeRowidIntent( context, rowid );
|
||||
|
@ -1102,8 +1102,12 @@ public class GameUtils {
|
|||
msg = bmr.m_chat;
|
||||
}
|
||||
} else if ( null != bmr.m_lmi ) {
|
||||
titleID = R.string.notify_title_fmt;
|
||||
msg = bmr.m_lmi.format( context ); // NPE
|
||||
if ( isTurnNow ) {
|
||||
titleID = R.string.notify_title_turn_fmt;
|
||||
} else {
|
||||
titleID = R.string.notify_title_fmt;
|
||||
}
|
||||
msg = bmr.m_lmi.format( context );
|
||||
}
|
||||
|
||||
if ( 0 != titleID ) {
|
||||
|
|
|
@ -60,14 +60,15 @@ import junit.framework.Assert;
|
|||
|
||||
import org.eehouse.android.xw4.DBUtils.GameChangeType;
|
||||
import org.eehouse.android.xw4.DBUtils.GameGroupInfo;
|
||||
import org.eehouse.android.xw4.DBUtils.SentInvitesInfo;
|
||||
import org.eehouse.android.xw4.DlgDelegate.Action;
|
||||
import org.eehouse.android.xw4.DlgDelegate.ActionPair;
|
||||
import org.eehouse.android.xw4.DwnldDelegate.DownloadFinishedListener;
|
||||
import org.eehouse.android.xw4.DwnldDelegate.OnGotLcDictListener;
|
||||
import org.eehouse.android.xw4.jni.*;
|
||||
import org.eehouse.android.xw4.jni.CommsAddrRec.CommsConnType;
|
||||
import org.eehouse.android.xw4.jni.CommsAddrRec.CommsConnTypeSet;
|
||||
import org.eehouse.android.xw4.loc.LocUtils;
|
||||
import org.eehouse.android.xw4.DwnldDelegate.DownloadFinishedListener;
|
||||
import org.eehouse.android.xw4.DwnldDelegate.OnGotLcDictListener;
|
||||
|
||||
public class GamesListDelegate extends ListDelegateBase
|
||||
implements OnItemLongClickListener,
|
||||
|
@ -1517,21 +1518,22 @@ public class GamesListDelegate extends ListDelegateBase
|
|||
public void onCreateContextMenu( ContextMenu menu, View view,
|
||||
ContextMenuInfo menuInfo )
|
||||
{
|
||||
boolean enable;
|
||||
super.onCreateContextMenu( menu, view, menuInfo );
|
||||
|
||||
int id = 0;
|
||||
boolean selected = false;
|
||||
long gameRowID = 0;
|
||||
GameListItem item = null;
|
||||
AdapterView.AdapterContextMenuInfo info
|
||||
= (AdapterView.AdapterContextMenuInfo)menuInfo;
|
||||
View targetView = info.targetView;
|
||||
DbgUtils.logf( "onCreateContextMenu(t=%s)",
|
||||
targetView.getClass().getName() );
|
||||
if ( targetView instanceof GameListItem ) {
|
||||
item = (GameListItem)targetView;
|
||||
id = R.menu.games_list_game_menu;
|
||||
|
||||
gameRowID = ((GameListItem)targetView).getRowID();
|
||||
selected = m_selGames.contains( gameRowID );
|
||||
selected = m_selGames.contains( item.getRowID() );
|
||||
} else if ( targetView instanceof GameListGroup ) {
|
||||
id = R.menu.games_list_group_menu;
|
||||
|
||||
|
@ -1548,12 +1550,17 @@ public class GamesListDelegate extends ListDelegateBase
|
|||
? R.id.games_game_select : R.id.games_game_deselect;
|
||||
Utils.setItemVisible( menu, hideId, false );
|
||||
|
||||
if ( 0 != gameRowID ) {
|
||||
boolean enable = BoardDelegate.rematchSupported( m_activity,
|
||||
gameRowID );
|
||||
if ( null != item ) {
|
||||
enable = BoardDelegate.rematchSupported( m_activity,
|
||||
item.getRowID() );
|
||||
Utils.setItemVisible( menu, R.id.games_game_rematch, enable );
|
||||
|
||||
enable = item.getSummary().isMultiGame()
|
||||
&& (BuildConfig.DEBUG || XWPrefs.getDebugEnabled( m_activity ));
|
||||
Utils.setItemVisible( menu, R.id.games_game_invites, enable );
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public boolean onContextItemSelected( MenuItem item )
|
||||
|
@ -1714,6 +1721,21 @@ public class GamesListDelegate extends ListDelegateBase
|
|||
m_rowid = selRowIDs[0];
|
||||
showDialog( DlgID.RENAME_GAME );
|
||||
break;
|
||||
|
||||
// DEBUG only
|
||||
case R.id.games_game_invites:
|
||||
msg = DBUtils.getSummary( m_activity, selRowIDs[0] )
|
||||
.conTypes.toString( m_activity );
|
||||
msg = getString( R.string.invites_net_fmt, msg );
|
||||
|
||||
SentInvitesInfo info = DBUtils.getInvitesFor( m_activity,
|
||||
selRowIDs[0] );
|
||||
if ( null != info ) {
|
||||
msg += "\n\n" + info.getAsText( m_activity );
|
||||
}
|
||||
showOKOnlyDialog( msg );
|
||||
break;
|
||||
|
||||
default:
|
||||
handled = false;
|
||||
}
|
||||
|
@ -1986,7 +2008,7 @@ public class GamesListDelegate extends ListDelegateBase
|
|||
{
|
||||
NetLaunchInfo nli = null;
|
||||
if ( MultiService.isMissingDictIntent( intent ) ) {
|
||||
nli = new NetLaunchInfo( m_activity, intent );
|
||||
nli = MultiService.getMissingDictData( m_activity, intent );
|
||||
} else {
|
||||
Uri data = intent.getData();
|
||||
if ( null != data ) {
|
||||
|
@ -2045,9 +2067,8 @@ public class GamesListDelegate extends ListDelegateBase
|
|||
DBUtils.setName( m_activity, newid, gameName );
|
||||
} else {
|
||||
long groupID = DBUtils.getGroupForGame( m_activity, srcRowID );
|
||||
newid = GameUtils.makeNewMultiGame( m_activity, groupID,
|
||||
dict, lang,
|
||||
addrs, gameName );
|
||||
newid = GameUtils.makeNewMultiGame( m_activity, groupID, dict,
|
||||
lang, addrs, gameName );
|
||||
DBUtils.addRematchInfo( m_activity, newid, btAddr, phone,
|
||||
relayID );
|
||||
}
|
||||
|
|
|
@ -40,8 +40,10 @@ abstract class InviteDelegate extends ListDelegateBase
|
|||
public static final String DEVS = "DEVS";
|
||||
public static final String COUNTS = "COUNTS";
|
||||
protected static final String INTENT_KEY_NMISSING = "NMISSING";
|
||||
protected static final String INTENT_KEY_LASTDEV = "LDEV";
|
||||
|
||||
protected int m_nMissing;
|
||||
protected String m_lastDev;
|
||||
protected Button m_okButton;
|
||||
protected Button m_rescanButton;
|
||||
protected Button m_clearButton;
|
||||
|
@ -56,6 +58,7 @@ abstract class InviteDelegate extends ListDelegateBase
|
|||
m_activity = delegator.getActivity();
|
||||
Intent intent = getIntent();
|
||||
m_nMissing = intent.getIntExtra( INTENT_KEY_NMISSING, -1 );
|
||||
m_lastDev = intent.getStringExtra( INTENT_KEY_LASTDEV );
|
||||
}
|
||||
|
||||
protected void init( int button_invite, int button_rescan,
|
||||
|
|
|
@ -26,6 +26,8 @@ import android.content.Context;
|
|||
import android.content.Intent;
|
||||
import android.content.DialogInterface.OnClickListener;
|
||||
|
||||
import junit.framework.Assert;
|
||||
|
||||
import org.eehouse.android.xw4.loc.LocUtils;
|
||||
|
||||
public class MultiService {
|
||||
|
@ -43,7 +45,7 @@ public class MultiService {
|
|||
public static final String OWNER = "OWNER";
|
||||
public static final String BT_NAME = "BT_NAME";
|
||||
public static final String BT_ADDRESS = "BT_ADDRESS";
|
||||
public static final String NLI_DATA = "nli";
|
||||
private static final String NLI_DATA = "nli";
|
||||
|
||||
public enum DictFetchOwner { _NONE,
|
||||
OWNER_SMS,
|
||||
|
@ -128,6 +130,15 @@ public class MultiService {
|
|||
return result;
|
||||
}
|
||||
|
||||
public static NetLaunchInfo getMissingDictData( Context context,
|
||||
Intent intent )
|
||||
{
|
||||
Assert.assertTrue( isMissingDictIntent( intent ) );
|
||||
String nliData = intent.getStringExtra( NLI_DATA );
|
||||
NetLaunchInfo nli = new NetLaunchInfo( context, nliData );
|
||||
return nli;
|
||||
}
|
||||
|
||||
public static Dialog missingDictDialog( Context context, Intent intent,
|
||||
OnClickListener onDownload,
|
||||
OnClickListener onDecline )
|
||||
|
@ -159,7 +170,7 @@ public class MultiService {
|
|||
// resend the intent, but only if the dict it names is here. (If
|
||||
// it's not, we may need to try again later, e.g. because our cue
|
||||
// was a focus gain.)
|
||||
static boolean returnOnDownload( Context context, Intent intent )
|
||||
public static boolean returnOnDownload( Context context, Intent intent )
|
||||
{
|
||||
boolean downloaded = isMissingDictIntent( intent );
|
||||
if ( downloaded ) {
|
||||
|
|
|
@ -88,13 +88,6 @@ public class NetLaunchInfo {
|
|||
init( context, data );
|
||||
}
|
||||
|
||||
public NetLaunchInfo( Context context, Intent intent )
|
||||
{
|
||||
String data = intent.getStringExtra( MultiService.NLI_DATA );
|
||||
Assert.assertNotNull( data );
|
||||
init( context, data );
|
||||
}
|
||||
|
||||
private NetLaunchInfo( Bundle bundle )
|
||||
{
|
||||
lang = bundle.getInt( MultiService.LANG );
|
||||
|
|
|
@ -82,11 +82,7 @@ public class NetStateCache {
|
|||
|
||||
boolean netAvail = getIsConnected( context );
|
||||
if ( netAvail ) {
|
||||
String msg = "netAvail(): second-guessing successful!!!";
|
||||
DbgUtils.logf( msg );
|
||||
if ( BuildConfig.DEBUG ) {
|
||||
Utils.showToast( context, msg );
|
||||
}
|
||||
DbgUtils.logf( "netAvail(): second-guessing successful!!!" );
|
||||
s_netAvail = true;
|
||||
if ( null != s_receiver ) {
|
||||
s_receiver.notifyStateChanged( context );
|
||||
|
|
|
@ -53,8 +53,6 @@ import org.eehouse.android.xw4.jni.CommsAddrRec;
|
|||
import org.eehouse.android.xw4.jni.GameSummary;
|
||||
import org.eehouse.android.xw4.jni.LastMoveInfo;
|
||||
import org.eehouse.android.xw4.jni.UtilCtxt.DevIDType;
|
||||
import org.eehouse.android.xw4.jni.UtilCtxt;
|
||||
import org.eehouse.android.xw4.jni.UtilCtxtImpl;
|
||||
import org.eehouse.android.xw4.jni.XwJNI;
|
||||
import org.eehouse.android.xw4.loc.LocUtils;
|
||||
|
||||
|
@ -256,8 +254,8 @@ public class RelayService extends XWService
|
|||
// make the initial connection -- needs access to util. That
|
||||
// should be fixable -- eventually.
|
||||
RelayMsgSink sink = new RelayMsgSink();
|
||||
UtilCtxt util = new UtilCtxtImpl( this );
|
||||
long rowid = GameUtils.makeNewMultiGame( this, nli, sink, util );
|
||||
long rowid = GameUtils.makeNewMultiGame( this, nli, sink,
|
||||
getUtilCtxt() );
|
||||
if ( DBUtils.ROWID_NOTFOUND != rowid ) {
|
||||
if ( null != nli.gameName && 0 < nli.gameName.length() ) {
|
||||
DBUtils.setName( this, rowid, nli.gameName );
|
||||
|
@ -452,7 +450,8 @@ public class RelayService extends XWService
|
|||
startService( this ); // bad name: will *stop* threads too
|
||||
}
|
||||
|
||||
private void setupNotifications( String[] relayIDs, BackMoveResult[] bmrs )
|
||||
private void setupNotifications( String[] relayIDs, BackMoveResult[] bmrs,
|
||||
ArrayList<Boolean> locals )
|
||||
{
|
||||
for ( int ii = 0; ii < relayIDs.length; ++ii ) {
|
||||
String relayID = relayIDs[ii];
|
||||
|
@ -460,7 +459,8 @@ public class RelayService extends XWService
|
|||
long[] rowids = DBUtils.getRowIDsFor( this, relayID );
|
||||
if ( null != rowids ) {
|
||||
for ( long rowid : rowids ) {
|
||||
GameUtils.postMoveNotification( this, rowid, bmr );
|
||||
GameUtils.postMoveNotification( this, rowid, bmr,
|
||||
locals.get(ii) );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -993,9 +993,10 @@ public class RelayService extends XWService
|
|||
RelayMsgSink sink = new RelayMsgSink();
|
||||
sink.setRowID( rowid );
|
||||
BackMoveResult bmr = new BackMoveResult();
|
||||
boolean[] isLocalP = new boolean[1];
|
||||
if ( GameUtils.feedMessage( this, rowid, msg, s_addr,
|
||||
sink, bmr ) ) {
|
||||
GameUtils.postMoveNotification( this, rowid, bmr );
|
||||
sink, bmr, isLocalP ) ) {
|
||||
GameUtils.postMoveNotification( this, rowid, bmr, isLocalP[0] );
|
||||
} else {
|
||||
DbgUtils.logdf( "feedMessage(): background dropped it" );
|
||||
}
|
||||
|
@ -1018,9 +1019,11 @@ public class RelayService extends XWService
|
|||
RelayMsgSink sink = new RelayMsgSink();
|
||||
int nameCount = relayIDs.length;
|
||||
ArrayList<String> idsWMsgs = new ArrayList<String>( nameCount );
|
||||
ArrayList<Boolean> isLocals = new ArrayList<Boolean>( nameCount );
|
||||
ArrayList<BackMoveResult> bmrs =
|
||||
new ArrayList<BackMoveResult>( nameCount );
|
||||
|
||||
boolean[] isLocalP = new boolean[1];
|
||||
for ( int ii = 0; ii < nameCount; ++ii ) {
|
||||
byte[][] forOne = msgs[ii];
|
||||
|
||||
|
@ -1028,12 +1031,15 @@ public class RelayService extends XWService
|
|||
if ( null != forOne ) {
|
||||
BackMoveResult bmr = new BackMoveResult();
|
||||
sink.setRowID( rowIDs[ii] );
|
||||
// since BoardDelegate.feedMessages can't know:
|
||||
isLocalP[0] = false;
|
||||
if ( BoardDelegate.feedMessages( rowIDs[ii], forOne, s_addr )
|
||||
|| GameUtils.feedMessages( this, rowIDs[ii],
|
||||
forOne, s_addr,
|
||||
sink, bmr ) ) {
|
||||
sink, bmr, isLocalP ) ) {
|
||||
idsWMsgs.add( relayIDs[ii] );
|
||||
bmrs.add( bmr );
|
||||
isLocals.add( isLocalP[0] );
|
||||
} else {
|
||||
DbgUtils.logf( "RelayService.process(): message for %s (rowid %d)"
|
||||
+ " not consumed", relayIDs[ii], rowIDs[ii] );
|
||||
|
@ -1045,7 +1051,7 @@ public class RelayService extends XWService
|
|||
idsWMsgs.toArray( tmp );
|
||||
BackMoveResult[] bmrsa = new BackMoveResult[bmrs.size()];
|
||||
bmrs.toArray( bmrsa );
|
||||
setupNotifications( tmp, bmrsa );
|
||||
setupNotifications( tmp, bmrsa, isLocals );
|
||||
}
|
||||
sink.send( this );
|
||||
}
|
||||
|
|
|
@ -49,6 +49,7 @@ import java.util.Map;
|
|||
import junit.framework.Assert;
|
||||
|
||||
import org.eehouse.android.xw4.DlgDelegate.Action;
|
||||
import org.eehouse.android.xw4.DBUtils.SentInvitesInfo;
|
||||
|
||||
public class SMSInviteDelegate extends InviteDelegate {
|
||||
|
||||
|
@ -63,11 +64,16 @@ public class SMSInviteDelegate extends InviteDelegate {
|
|||
private boolean m_immobileConfirmed;
|
||||
private Activity m_activity;
|
||||
|
||||
public static void launchForResult( Activity activity, int nMissing,
|
||||
public static void launchForResult( Activity activity, int nMissing,
|
||||
SentInvitesInfo info,
|
||||
RequestCode requestCode )
|
||||
{
|
||||
Intent intent = new Intent( activity, SMSInviteActivity.class );
|
||||
intent.putExtra( INTENT_KEY_NMISSING, nMissing );
|
||||
if ( null != info ) {
|
||||
String lastDev = info.getLastDev( InviteMeans.SMS );
|
||||
intent.putExtra( INTENT_KEY_LASTDEV, lastDev );
|
||||
}
|
||||
activity.startActivityForResult( intent, requestCode.ordinal() );
|
||||
}
|
||||
|
||||
|
@ -327,7 +333,8 @@ public class SMSInviteDelegate extends InviteDelegate {
|
|||
|
||||
m_phoneRecs = new ArrayList<PhoneRec>(phones.length);
|
||||
for ( String phone : phones ) {
|
||||
PhoneRec rec = new PhoneRec( phone );
|
||||
boolean matches = phone.equals( m_lastDev );
|
||||
PhoneRec rec = new PhoneRec( null, phone, matches );
|
||||
m_phoneRecs.add( rec );
|
||||
}
|
||||
}
|
||||
|
@ -369,6 +376,24 @@ public class SMSInviteDelegate extends InviteDelegate {
|
|||
saveAndRebuild();
|
||||
}
|
||||
|
||||
private void clearIfSingle()
|
||||
{
|
||||
if ( 1 == m_nMissing ) {
|
||||
int count = m_adapter.getCount();
|
||||
for ( int ii = count - 1; ii >= 0; --ii ) {
|
||||
PhoneRec rec = m_phoneRecs.get( ii );
|
||||
if ( rec.m_isChecked ) {
|
||||
rec.m_isChecked = false;
|
||||
}
|
||||
}
|
||||
post( new Runnable() {
|
||||
public void run() {
|
||||
rebuildList( false );
|
||||
}
|
||||
} );
|
||||
}
|
||||
}
|
||||
|
||||
private class PhoneRec {
|
||||
public String m_phone;
|
||||
public String m_name;
|
||||
|
@ -383,7 +408,7 @@ public class SMSInviteDelegate extends InviteDelegate {
|
|||
this( null, phone, false );
|
||||
}
|
||||
|
||||
public PhoneRec( String name, String phone, boolean checked )
|
||||
private PhoneRec( String name, String phone, boolean checked )
|
||||
{
|
||||
m_phone = phone;
|
||||
m_isChecked = checked;
|
||||
|
@ -424,6 +449,7 @@ public class SMSInviteDelegate extends InviteDelegate {
|
|||
new CompoundButton.OnCheckedChangeListener() {
|
||||
public void onCheckedChanged( CompoundButton bv,
|
||||
boolean isChecked ) {
|
||||
clearIfSingle();
|
||||
m_phoneRecs.get(position).m_isChecked = isChecked;
|
||||
tryEnable();
|
||||
}
|
||||
|
|
|
@ -56,6 +56,7 @@ import java.util.Set;
|
|||
import junit.framework.Assert;
|
||||
|
||||
import org.eehouse.android.xw4.GameUtils.BackMoveResult;
|
||||
import org.eehouse.android.xw4.MultiService.DictFetchOwner;
|
||||
import org.eehouse.android.xw4.MultiService.MultiEvent;
|
||||
import org.eehouse.android.xw4.jni.CommsAddrRec.CommsConnType;
|
||||
import org.eehouse.android.xw4.jni.CommsAddrRec;
|
||||
|
@ -348,20 +349,15 @@ public class SMSService extends XWService {
|
|||
inviteRemote( phone, intent.getStringExtra( GAMEDATA_STR ) );
|
||||
break;
|
||||
case ADDED_MISSING:
|
||||
NetLaunchInfo nli
|
||||
= MultiService.getMissingDictData( this, intent );
|
||||
phone = intent.getStringExtra( PHONE );
|
||||
int gameID = intent.getIntExtra( MultiService.GAMEID, -1 );
|
||||
String gameName = intent.getStringExtra( MultiService.GAMENAME );
|
||||
int lang = intent.getIntExtra( MultiService.LANG, -1 );
|
||||
String dict = intent.getStringExtra( MultiService.DICT );
|
||||
int nPlayersT = intent.getIntExtra( MultiService.NPLAYERST, -1 );
|
||||
int nPlayersH = intent.getIntExtra( MultiService.NPLAYERSH, -1 );
|
||||
makeForInvite( phone, gameID, gameName, lang, dict,
|
||||
nPlayersT, nPlayersH, 1 );
|
||||
makeForInvite( phone, nli );
|
||||
break;
|
||||
case SEND:
|
||||
phone = intent.getStringExtra( PHONE );
|
||||
byte[] bytes = intent.getByteArrayExtra( BINBUFFER );
|
||||
gameID = intent.getIntExtra( MultiService.GAMEID, -1 );
|
||||
int gameID = intent.getIntExtra( MultiService.GAMEID, -1 );
|
||||
sendPacket( phone, gameID, bytes );
|
||||
break;
|
||||
case REMOVE:
|
||||
|
@ -512,18 +508,11 @@ public class SMSService extends XWService {
|
|||
if ( DictLangCache.haveDict( this, nli.lang, nli.dict ) ) {
|
||||
makeForInvite( phone, nli );
|
||||
} else {
|
||||
Assert.fail();
|
||||
// Intent intent = MultiService
|
||||
// .makeMissingDictIntent( this, gameName, lang, dict,
|
||||
// nPlayersT, nPlayersH );
|
||||
// intent.putExtra( PHONE, phone );
|
||||
// intent.putExtra( MultiService.OWNER,
|
||||
// MultiService.OWNER_SMS );
|
||||
// intent.putExtra( MultiService.INVITER,
|
||||
// Utils.phoneToContact( this, phone, true ) );
|
||||
// intent.putExtra( MultiService.GAMEID, gameID );
|
||||
// MultiService.postMissingDictNotification( this, intent,
|
||||
// gameID );
|
||||
Intent intent = MultiService
|
||||
.makeMissingDictIntent( this, nli,
|
||||
DictFetchOwner.OWNER_SMS );
|
||||
MultiService.postMissingDictNotification( this, intent,
|
||||
nli.gameID() );
|
||||
}
|
||||
} else {
|
||||
DbgUtils.logf( "invalid nli from: %s", nliData );
|
||||
|
@ -648,24 +637,13 @@ public class SMSService extends XWService {
|
|||
|
||||
private void makeForInvite( String phone, NetLaunchInfo nli )
|
||||
{
|
||||
SMSMsgSink sink = new SMSMsgSink( this );
|
||||
long rowid = GameUtils.makeNewMultiGame( this, nli, sink, null );
|
||||
long rowid = GameUtils.makeNewMultiGame( this, nli,
|
||||
new SMSMsgSink( this ),
|
||||
getUtilCtxt() );
|
||||
postNotification( phone, nli.gameID(), rowid );
|
||||
ackInvite( phone, nli.gameID() );
|
||||
}
|
||||
|
||||
private void makeForInvite( String phone, int gameID, String gameName,
|
||||
int lang, String dict, int nPlayersT,
|
||||
int nPlayersH, int forceChannel )
|
||||
{
|
||||
long rowid =
|
||||
GameUtils.makeNewGame( this, gameID, new CommsAddrRec( phone ),
|
||||
lang, dict, nPlayersT, nPlayersH,
|
||||
forceChannel, gameName );
|
||||
postNotification( phone, gameID, rowid );
|
||||
ackInvite( phone, gameID );
|
||||
}
|
||||
|
||||
private PendingIntent makeStatusIntent( String msg )
|
||||
{
|
||||
Intent intent = new Intent( msg );
|
||||
|
@ -729,6 +707,7 @@ public class SMSService extends XWService {
|
|||
if ( null == rowids || 0 == rowids.length ) {
|
||||
sendDiedPacket( addr.sms_phone, gameID );
|
||||
} else {
|
||||
boolean[] isLocalP = new boolean[1];
|
||||
for ( long rowid : rowids ) {
|
||||
if ( BoardDelegate.feedMessage( rowid, msg, addr ) ) {
|
||||
// do nothing
|
||||
|
@ -736,8 +715,9 @@ public class SMSService extends XWService {
|
|||
SMSMsgSink sink = new SMSMsgSink( this );
|
||||
BackMoveResult bmr = new BackMoveResult();
|
||||
if ( GameUtils.feedMessage( this, rowid, msg, addr,
|
||||
sink, bmr ) ) {
|
||||
GameUtils.postMoveNotification( this, rowid, bmr );
|
||||
sink, bmr, isLocalP ) ) {
|
||||
GameUtils.postMoveNotification( this, rowid, bmr,
|
||||
isLocalP[0] );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -136,7 +136,12 @@ public class Utils {
|
|||
|
||||
public static void showToast( Context context, String msg )
|
||||
{
|
||||
Toast.makeText( context, msg, Toast.LENGTH_SHORT).show();
|
||||
// Make this safe to call from non-looper threads
|
||||
try {
|
||||
Toast.makeText( context, msg, Toast.LENGTH_SHORT).show();
|
||||
} catch ( java.lang.RuntimeException re ) {
|
||||
DbgUtils.loge( re );
|
||||
}
|
||||
}
|
||||
|
||||
public static void showToast( Context context, int id )
|
||||
|
|
|
@ -28,13 +28,16 @@ import java.util.HashSet;
|
|||
import java.util.Set;
|
||||
|
||||
import org.eehouse.android.xw4.MultiService.MultiEvent;
|
||||
|
||||
import org.eehouse.android.xw4.jni.UtilCtxt;
|
||||
import org.eehouse.android.xw4.jni.UtilCtxtImpl;
|
||||
|
||||
public class XWService extends Service {
|
||||
|
||||
protected static MultiService s_srcMgr = null;
|
||||
private static Set<String> s_seen = new HashSet<String>();
|
||||
|
||||
private UtilCtxt m_utilCtxt;
|
||||
|
||||
@Override
|
||||
public IBinder onBind( Intent intent )
|
||||
{
|
||||
|
@ -74,4 +77,12 @@ public class XWService extends Service {
|
|||
DbgUtils.logf( "XWService.checkNotDupe(%s) => %b", inviteID, !isDupe );
|
||||
return !isDupe;
|
||||
}
|
||||
|
||||
protected UtilCtxt getUtilCtxt()
|
||||
{
|
||||
if ( null == m_utilCtxt ) {
|
||||
m_utilCtxt = new UtilCtxtImpl( this );
|
||||
}
|
||||
return m_utilCtxt;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -27,6 +27,7 @@ import java.util.Iterator;
|
|||
import junit.framework.Assert;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import org.eehouse.android.xw4.DBUtils;
|
||||
import org.eehouse.android.xw4.DbgUtils;
|
||||
import org.eehouse.android.xw4.R;
|
||||
import org.eehouse.android.xw4.Utils;
|
||||
|
@ -196,15 +197,26 @@ public class GameSummary {
|
|||
|
||||
// FIXME: should report based on whatever conType is giving us a
|
||||
// successful connection.
|
||||
public String summarizeRole()
|
||||
public String summarizeRole( long rowid )
|
||||
{
|
||||
String result = null;
|
||||
if ( isMultiGame() ) {
|
||||
int fmtID = 0;
|
||||
|
||||
int missing = countMissing();
|
||||
if ( 0 < missing ) {
|
||||
DBUtils.SentInvitesInfo si = DBUtils.getInvitesFor( m_context,
|
||||
rowid );
|
||||
if ( si.getMinPlayerCount() >= missing ) {
|
||||
result = LocUtils.getString( m_context,
|
||||
R.string.summary_invites_out );
|
||||
}
|
||||
}
|
||||
|
||||
// If we're using relay to connect, get status from that
|
||||
if ( conTypes.contains( CommsConnType.COMMS_CONN_RELAY ) ) {
|
||||
if ( anyMissing() ) {
|
||||
if ( null == result
|
||||
&& conTypes.contains( CommsConnType.COMMS_CONN_RELAY ) ) {
|
||||
if ( 0 < missing ) {
|
||||
if ( null == relayID || 0 == relayID.length() ) {
|
||||
fmtID = R.string.summary_relay_conf_fmt;
|
||||
} else {
|
||||
|
@ -222,7 +234,7 @@ public class GameSummary {
|
|||
if ( null == result ) {
|
||||
if ( conTypes.contains( CommsConnType.COMMS_CONN_BT )
|
||||
|| ( conTypes.contains( CommsConnType.COMMS_CONN_SMS))){
|
||||
if ( anyMissing() ) {
|
||||
if ( 0 < missing ) {
|
||||
if ( DeviceRole.SERVER_ISSERVER == serverRole ) {
|
||||
fmtID = R.string.summary_wait_host;
|
||||
} else {
|
||||
|
@ -277,16 +289,20 @@ public class GameSummary {
|
|||
return result;
|
||||
}
|
||||
|
||||
public boolean anyMissing()
|
||||
private int countMissing()
|
||||
{
|
||||
boolean missing = false;
|
||||
int result = 0;
|
||||
for ( int ii = 0; ii < nPlayers; ++ii ) {
|
||||
if ( !isLocal(ii) && (0 != ((1 << ii) & missingPlayers) ) ) {
|
||||
missing = true;
|
||||
break;
|
||||
++result;
|
||||
}
|
||||
}
|
||||
return missing;
|
||||
return result;
|
||||
}
|
||||
|
||||
public boolean anyMissing()
|
||||
{
|
||||
return 0 < countMissing();
|
||||
}
|
||||
|
||||
public int giflags() {
|
||||
|
@ -445,7 +461,7 @@ public class GameSummary {
|
|||
break;
|
||||
}
|
||||
}
|
||||
DbgUtils.logf( "hasRematchInfo() => %b", found );
|
||||
// DbgUtils.logf( "hasRematchInfo() => %b", found );
|
||||
}
|
||||
return found;
|
||||
}
|
||||
|
|
|
@ -382,7 +382,9 @@ DBMgr::RegisterDevice( const DevID* host, int clientVersion,
|
|||
// coming from random, but test with increasing values initially to make
|
||||
// sure duplicates are detected.
|
||||
const char* devidStr = host->m_devIDString.c_str();
|
||||
for ( bool success = false, ii = 0; !success; ++ii ) {
|
||||
int ii;
|
||||
bool success;
|
||||
for ( success = false, ii = 0; !success; ++ii ) {
|
||||
assert( 10 > ii ); // better to check that we're looping BECAUSE
|
||||
// of uniqueness problem.
|
||||
do {
|
||||
|
|
Loading…
Reference in a new issue