Since display is now by whose turn it is and how recently there's been a
move in the game, the order can change on every save. So in the listener
for saves, redraw the group the saved game belongs to. The best way to
do this without flicker seems to be to mimic closing then re-expanding
the group, so that's what I'm doing.
Getting an NPE iterating over fragment/children of dualpane view
because, I think, committing them's been postponed. So add the iteration
as a Runnable to the same postponement mechanism. This may be wrong:
needs to be run for a while to see if it fixes the NPEs I'm seeing (on
opening an intent in the morning after the device has been idle all
night.)
Attempt to fix crashes happening when the occasional fragment
transaction happens before the OS is ready. Keep a boolean indicating
whether we're in that state, and when it's not set create a Runnable to
be run next time it is. Temporary Toast lets me know when it's working.
Attempt to fix crashes happening when the occasional fragment
transaction happens before the OS is ready. Keep a boolean indicating
whether we're in that state, and when it's not set create a Runnable to
be run next time it is. Temporary Toast lets me know when it's working.
Problem: brain-dead Android code (on 5.1.0 anyway) caches the
SectionIndexer separately from the ListAdapter that implements it, so
when you change the ListAdapter it keeps using the old one for its
SectionIndexer. Solution is to replace the ListView in the layout with a
FrameLayout into which a ListView is inserted at runtime on init and
whenever the data changes.
Setting up an emulator that'll grab {menu,layout}-small resources is a
pain so this script exchanges them with regular resources so that a
subsequent compile will produce something that (when run) will catch
missing resources etc.
tweaks to BoardContainer and Toolbar to better position toolbar and
better hide/show it in tile exchange mode. The bar's still partially
offscreen sometimes on a 2.3.7 emulator but it's usable. Next I need to
try specifying the size of the bar rather than having it derive from the
size of the images it contains.
They crash on 2.3.7 at least, and don't seem to be required anyway. I
think the only reason I need to implement onMeasure() is because
BoardView expects to be called a certain way.
Correct or not, this is my solution to the circular problem of how to
choose a vertical or horizontal toolbar before beginning the layout of
the board and toolbar. Adding a new custom container that holds the
board, toolbar(s) and tile exchange buttons and uses the ratio of its
own dimensions to choose which toolbar to show. Also drive toolbar
initialization from the layout process because when started from
BoardDelegate it now tries to install button listeners too early.
Fix crash when game config opens dict download for result and nothing's
chosen. Was sending Activity.RESULT_OK in that case instead of
RESULT_CANCELED.
Docs and some logcat crash statements from the OS say I need no-args
constructors for fragments. So rework initialization and use bundling so
parent name doesn't have to be passed into the constructor. Seems to
work, and fixes the crash I was seeing (happened when sending an
invitation via SMS) but requires more testing.
Fixing a crash when a game offers both to create a rematch and to delete
itself because its opponent has been deleted. Deleting and then hitting
rematch would crash because the rematch alert referred to a dead
game. Now onStop() for delegates removes any pending alerts. In
dual-pane mode only since when there's an activity going away the alerts
go automatically.
Rather than have callers of getSummary() try JNIThread for the lock, do
that check inside getSummary(), and move it to GameUtils from DBUtils
since it's using higher-level knowledge now.
Add new parameterless setTitle() method on delegates, and call it when a
fragment is removed so the new right-most pane can restore a title that
makes sense. So far only board and gameconfig delegates implement this
new method.
Current GameLock implementation means you can't get a lock for an open
game, so try getting one from an existing JNIThread instance
first. Which is a hack that's start to appear in lots of places.... Also
fix so just in case we are unable to lock a game we drop the rematch
process rather than crash in an assert later. The test case: rematch a
solo game that's currently open in the right pane.
Fixed race conditions revealed by dual-pane mode where GameLock could be
instantiated and then attempts made to reference its game (jni calls)
before it had been loaded. So now loading happens inside the same
synchronized methods as opening or creating a game.
Rare crashes are happening inside the jni, in game_dispose(), when a
game's double-disposed. Adding a jni call to check if the thread about
to do a game_dispose() will fail then asserting its result in java
allows useful stack traces to come via Crittercism. Or should.
There was a race condition between finish() and the popping of fragments
that happens inside dispatchNewIntent(). If dispatchNewIntent() won then
later finish() would pop the GamesListFragment and we'd crash. Ideally
finish() would pass a fragment to finishFragment() which would then do
nothing if that fragment wasn't on the stack. Later....
better strings, and explain when pref changed that user must restart for
it to take effect. Actually restarting from inside prefs delegate is
hard enough I'm not doing it for what should be advanced users.
I want to use ReentrantLock instead of my implementation but I'm
breaking its rule that the thread that locks a lock must be the one to
unlock it. Add commented-out assertion for some later time when I might
want to fix this. No change for now.
Game created for rematch was coming up unconnected and without
explanation if recipient of invitation hadn't responded. Don't dismiss
the INVITE alert in that case.
This to prevent the game list item from resizing (and so reflowing the
whole list) when it's reloading game info. Better would be to set a
timer and only show the reloading view if it seems likely to take a
minute.
When a gtk3 window's shutting down it appears we can't get a cairo_t*
for it. This change makes it possible to turn that fact into aborting
the whole draw operation.
I'm seeing unreproducible crashes trying to double-dispose jni game
instances and think it's a race condition involving JNIThread. Forcing
it to hold the lock in the constructor, access to which is synchronized,
is an improvement and may well fix it.
When a device is a tablet and not a first-time install, put up an offer
to enable dual-pane mode. Change confirm-alerts to include
do-not-show-again box, and use that. Add menu item, hidden when not in
dual-pane mode, to turn it back off. Exit app after posting a
notification and a toast on changing that preference so it'll take
effect.
# Please enter a commit message to explain why this merge is necessary,
# especially if it merges an updated upstream into a topic branch.
#
# Lines starting with '#' will be ignored, and an empty message aborts
# the commit.
When app's launched via a move-made intent that will lead to opening
the board, let the GamesList fragment get fully in place before
opening the board. To open two at the same time confuses my fragment
code (OS kills it with a fatal exception.)
When during onResume() of BoardDelegate we notice an undisplayed chat
message, don't add add a Chat fragment because (perhaps due to a bug
in my code) it'll come up blank. Instead use post() to open it via a
Runnable() that'll run after onResume() and the rest of current
fragment setup have completed.
When loading gamelistitems in dual-pane mode there will often be an
open game. Don't hold up the whole process by first waiting 1 second
to get a lock that's unavailable. Instead check if there's a JNIThread
instance available and if so use its lock to get the summary. Required
fixing JNIThread to not crash trying to save when released too early.
Fixes, or at least makes extremely unlikely, race condition where one
thread makes use of an existing JNIThread instance then releases it
before the thread that created it has had a chance to call configure()
to actually load the game.
Problem was that changes to games didn't show up in the thumbnail
until the game was closed. Simply using existing snapshot didn't work
because it changes the board layout in order to "draw" to
ThumbnailCanvas and that change isn't easily reversed. So copy
existing code to open a new JNI object with just-saved game data
and use it to create a thumbnail bitmap.
They're often needed when the fragment isn't frontmost, i.e. when
onPause() has been called. My caching instances fix is feeling a bit
fragile, but I think it's better than nothing. Alternative is probably
to go with DialogFragments, a big change that might not be easy to
make work back to oldest Android.
There's a problem in dual-pane mode where activites outlive
DelegateBase instances that are tied to fragments. AlertDialogs, being
bound to the MainActivity, can sometimes outlive the delegates that
create them, meaning the 'this' referred to from closures bound to
onClick() handlers can come to be invalid (e.g. referencing a removed
fragment). So add a global registry of current DelegateBase instances
by class, and from onClick() handlers fetch and use the current
instance instead of the 'this' that's bound.
Inviting didn't work because it's done by a separate activity whose
onActivityResult() was dropped because DualpaneDelegate was the
recipient. That now handles it by asking MainActivity to sent it to a
contained Delegate. Currently will go only to the top (rightmost) one.
Was opening game in init(), but in dual-pane case there's no
onWindowFocusChanged() call from which to check state, so open it
instead from onResume(), at which point things are already in place to
handle callbacks immediately. That is, post() will work.
use s/getTargetFragment(), but there's still the hack of capturing
state in setResult() and then invoking fragment.onActivityResult()
blindly the next time the backstack is popped.
create queue of Runnables to be run only when Delegate is
visible (onResume() has been called and onPause() hasn't.) When
missing dict finishes downloading, rather than immediately opening its
game, post a Runnable to do it that will be run only after the main
activity is ready to have fragment transactions committing again.
When the game's already opened references must be obtained this
way. This may not be necessary however once game config is opened on
top of games list instead of on top of the game as it should be.
For some reason the 'clean-debug' cycle stopped working because the
file was nuked then not regenerated. Rather than figure out why, just
add a target to generate it every time.
On 4.2 and 4.3 at least, the dimiss comes after the second post
causing that to be dismissed, leaving no alert and the app in some
weird state where not even the back button works. It's been this way
on those older versions since I redid invitations for beta 98.
On 4.2 and 4.3 at least, the dimiss comes after the second post
causing that to be dismissed, leaving no alert and the app in some
weird state where not even the back button works. It's been this way
on those older versions since I redid invitations for beta 98.
Not doing so no longer crashes on when handling notifications, and is
causing runtime exceptions from the OS when board opening chat causes
it to be called recursively.
display problems with GamesList in dual-pane mode, I think because it
prevents stacked activities. Need to figure out if it introduces
problems elsewhere.
# Please enter a commit message to explain why this merge is necessary,
# especially if it merges an updated upstream into a topic branch.
#
# Lines starting with '#' will be ignored, and an empty message aborts
# the commit.
time to choose between dual-pane and regular mode that doesn't mess
up sending Intents and make it harder to prevent there being
multiple instances of activities that are supposed to be single-top.
in the process of being closed.) If we're successful in getting a
JNIThread object that's already initialized, re-use it, closing only
the JNI part (which probably can't be cleanly re-used with a different
Context.) I worry about the case where the thread's event queue isn't
empty, so there's an assert to catch that case.
whose lifespan matches its, e.g. the gameptr and gi. This is a big
change, and there are still some bugs/crashes, but it's worth
committing this snapshot.
board in dual-pane mode (that show up as all-white BoardView). I think
there was a slight reduction in frequency, which varies with screen
size at least.
orientation changes down to it (or any other interested delegate), and
have it lay its container out again. There appear to be race
conditions here: sometimes the toolbar winds up in the wrong
orientation, and on some devices the board can be blank. One problem
is that on a multi-paned device a single pane may be portrait (taller
than wide) though the whole device is in landscape mode. The big
challege is to get the view's max dimensions (and whether it's
landscape or portrait) when layout hasn't yet begun, because we that
for the jni part of layout. Messy still, but better than before and I
think progress in the right direction.
it replaces the right one rather than pushing the left off the
screen. Use that to make dictionary browser, chat, and studylist all
able to swap places while the open board is on the left.